Why does this C program crash? It compiled fine [duplicate] - c

This question already has an answer here:
Program crashes when trying to read numbers with scanf
(1 answer)
Closed 8 years ago.
This program compiles fine. When I input a number, it crashes on me. name.exe has stopped working But why?
int main (void) {
int arrayMax = 0;
printf ("How many numbers will be entered?\n");
scanf ("%i", arrayMax);
int i;
double userInput [arrayMax];
return 0;
}

scanf ("%i", &arrayMax);
Do this scan to the address using &. You need to pass the address of the variable to which you need to scan the value to. In this case your variable is arrayMax and you need to pass the address of this variable which the scanf() expects and in this case you are not doing so and passing 0 which is not the memory location to which you want to scan your value to so you see crash.
Writing to in-valid memory location causes crash.

You forget to place & operator in the scanf argument.
scanf ("%i", &arrayMax);
// ^Place unary & to specify the location.

scanf is a variadic function.
As such, the compiler cannot determine whether or not the type of each argument passed to it is correct (expect for the type of the first argument, which is explicitly declared as const char*).
As a result, the decision is "moved" from compile-time to run-time, and so instead of a compile-time error you might get a run-time error.
For example, in the case of scanf("%i"), the function expects the address of an int variable.
In your code you are passing the value 0, so scanf will first scan user-input, and then attempt to write it at that memory address.
If the memory segment which includes this address does not have Write access permission (for example, if the code-section of your program resides at that address), then this attempt will result with a memory access violation during runtime.
You can get it to work correctly by changing scanf("%i",arrayMax) to scanf("%i",&arrayMax).

Related

What does scanf do when passing a char and an integer specifier?

For the purposes of an exercise, I was given a snippet of code and told to find the bug. I removed a bunch of noise and the part that is tripping me up is the following:
int main() {
char *p;
char n;
scanf("%i", n);
if (n < get_int()) {
p = malloc(n);
}
}
Here, if I enter a number for n, I get a seg fault. If I enter a character, n is set to 0. What is scanf doing that makes this so?
Edit: the exercise I'm trying to figure out is Exercise 2 from this page
It is simply UB.
C does not specify any specific behavior here. "%i" expect a int *, not an uninitialized char converted to an int.
"What is scanf doing that makes this so?" implies defined behavior. There is no specified UB.
"If I enter a character, n is set to 0. " --> scanf() does not attempt to change n, it uses a copy of n (passed by value).
The usual scanf() usages is like the below where the address of nn is passed, not nn itself.
int nn;
if (scanf("%i", &nn) == 1) Success();
else Failure();
You aren't just passing the wrong kind of variable to scanf, you are also passing it's value instead of the pointer to it. The scanf have no way of knowing this value isn't an actual pointer to store the scanned data into, so thats exactly what its going to try and do, scan the input and place it into whatever memory address the n, treated as pointer value, happened to point to. In the absolute most of the cases this will attempt to access unmapped/protected/etc memory, and cause segfault/access violation.
Entering a character simply terminates the scan prematurely, avoiding the segfault, and leaving the n intact. Bit since the value of n isn't initialized, it can happen to be just about anything, any junk that happened to be on the stack at that point of time.

Difference between runtime and syntax error [duplicate]

This question already has answers here:
Is not using & with a variable in scanf() a syntax error or a runtime error?
(2 answers)
Closed 7 years ago.
I have a problem like this:
Q. Pick ANY error you can have from here:
int main(void)
{
int a;
printf("Input a integer number >>");
scanf("%d\n", a);
printf("The input number is %d\n", a);
return 0;
}
syntax error
logical error
run-time error
no error
I thought it was both syntax and run-time error because:
For syntax, there is no & in front of a.
For run-time error, the program would still be built to run the first print statement and suddenly stop at scanf() statement because there is no &.
However, I was told that I'm wrong.
I know that it is not logical error, but I'm confused which one is which.
Syntax errors are detected by compiler. This program compiles fine, so it does not have syntax errors.
However, this program passes the value of an uninitialized variable a to scanf, which is undefined behavior, i.e. a runtime error.
No, there will not be any syntax error here, only run-time error.
scanf() expects a pointer to the variable to store the value but that does not mandate that we have to use the & operator always to pass an address.
Imagine, in case a would have been a pointer (and allocated proper memory),
scanf("%d\n", a);
would have been a perfectly valid statement, isn't it?
In this code, you have passed the value of an uninitialized variable (which get tread as an address, which will be invalid) as an argument to the %d format specifier to scanf(), so that invokes undefined behavior that causes runtime error.

Why compiler is not issuing error while passing an int (not int *) as the argument of scanf()?

I tried the below c program & I expected to get compile time error, but why compiler isn't giving any error?
#include <stdio.h>
#include <conio.h>
int main()
{
int a,b;
printf("Enter a : ");
scanf("%d",&a);
printf("Enter b : ");
scanf("%d",b);
printf("a is %d and b is %d\n",a,b);
getch();
return 0;
}
I am not writing & in scanf("%d",b). At the compile time , compiler don't give any error but during execution value of b is 2686792(garbage value).
As per C11 standard, Chapter ยง6.3.2.3
An integer may be converted to any pointer type. Except as previously specified, the
result is implementation-defined, might not be correctly aligned, might not point to an
entity of the referenced type, and might be a trap representation.
So, the compiler will allow this, but the result is implementation-defined.
In this particular case, you're passing b to scanf() as an argument, which is uninitialized, which will cause the program to invoke undefined behaviour, once executed.
Also, printf() / scanf() being variadic functions, no check on paramater type is perforfmed in general, unless asked explicitly through compiler flag [See -Wformat].
It is not a a compile time error but a runtime issue.
The compiler expects that you have given a valid address to scan the value to, during runtime only it will come to know whether the address is valid or not .
If you try to scan the value to invalid address it leads to undefined behavior and might see a crash.
It scans fine because scanf expects a memory location in its argument. That's why we use & to give memory location of the corresponding variable.
In your case scanf just scans the entered value and puts it in the memory location which has the value of b(instead of scanning and putting it in the memory location where b is stored).
The & operator in C returns the address of the operand. If you give just the b without the & operator, it will be passed by value and the scanf won't be able to set the value. This would result in unexpected behaviour as you already noticed. It has no way of verifying the address before the runtime and hence you won't notice the issue until runtime.

Why does the strange value come out with an unnecessary % conversion in the code in C language?

I started learning programming only few days ago, so basically I have no knowledge.
I'm starting with C, and I wrote a very simple code which is:
int main (int argc, const char * argv[])
{
printf("%d + %d", 1 + 3);
return 0;
}
with the code above, I got the value of 4 + 1606416608 and later found that the return value is wrong because I put more %d than necessary. Then my question is, how did that strange value actually come out? If anyone knows, please help me. Thank you!!
You know what you did wrong already, so to explain what your particular implementation of C probably did:
When you call printf, a new stack frame is pushed to the call stack. The call stack is a last in first out structure with one 'frame' per called function. So if main called logStuff which called printf then three consecutive frames would be for main, then logStuff, then printf. When printf returns, it's frame is removed from the structure and execution continues with logStuff.
So a frame usually contains at least the parameters passed to the function and storage for local variables. Those things may be one and the same, it's implementation dependant.
With a variadic function like printf there's a stream of unnamed parameters. The bit patterns will be put into an appropriate place in the frame. But C is not a reflective language. Each bit patten doesn't inherently have a meaning: any one could be an integer, a float, or anything else. It also isn't a language that invests in bounds checking. You're trusted to write code that acts correctly.
printf determines the types and number of unnamed parameters from the string. So if you've given it false information, it will interpret the bit patterns with something other than their correct meaning and it may think there are fewer or more than are really there.
You told it there were more. So what probably happened was that the parameters were in the equivalent of an array and it read a value from beyond the end of the array. As it's all implementation dependent, that value may have been meant to represent anything. It could be the address of the caller. It could be uninitialised storage for another local variable. It could be bookkeeping. It could be the format string, incorrectly interpreted as an integer.
What it isn't is any reliable value. It may not even always be safe to read.
You are in undefined behavior land... you are telling a variadic function that you have 2 int sized params, then you only supply one, you are leaking something from the stack.
1) %d is a format specifier, it tells the compiler how you want to access the value stored at a particular location.(here as an integer)
2) For every format specifier you need to provide a corresponding variable or a value, otherwise at runtime you will get "garbage" i.e. some random value.
Example :
int main()
{
int a = 65;
printf("\na = %d", a); // here the value stored in a is accessed as an integer.
printf("\na = %c", a); // the value inside a is accessed as a character.
return 0;
}
In the above example '%d' in the first printf statement tells the compiler that the value stored in the variable a is to be accessed as an integer. (o/p - 65)
In the second printf statement '%c' is used to access the same variable as a character.(o/p - A)
Your code expects two numerical parameters to be printed, and you're giving it one.
Expected:
printf("%d + %d", <some_num>, <another_num>);
You're giving it:
printf("%d + %d", <some_num>);
Where <some_num> is what 1+3 evaluates to. The function expects another argument, but receives garbage instead.
What you should do is
printf("%d + %d = %d", 1, 3, 1+3);

Strange output of this C program

#include<stdio.h>
main()
{
int i;
char c;
for (i=0;i<5;i++){
scanf("%d",&c);
printf("%d",i);
}
printf("\n");
}
I thought it will print 0 1 2 3 4 but it didn't.
What's the reason of the strange output?
Undefined Behaviour.
You're attempting to read an int (the "%d" in the scanf call) into an object of type char (the c). Don't do that!
This program exhibits undefined behavior: The type of &c (char *) does not correspond to the type of the scanf arg (%d wants a signed int *).
What is probably happening is that the scanf is writing 4 bytes to the memory location starting at the address of c. Which is only 1 byte long, so the other 3 bytes overwrite the first 3 bytes of i's value. On a little-endian system, that would effectively set i to whatever integer value you enter shifted right by 8 bits.
But, of course, the behavior is undefined. Next time you compile this code, it could do something completely different. A different compiler, or the same compiler with different options, could keep i in a register (where scanf cannot overwrite it) (but it might instead smash the return address on the stack, causing a crash when the program ends), or it could put the values on the stack in the opposite order (same deal), or it could leave 4 bytes on the stack for c (causing no unexpected behavior), or it could detect the situation and abort with an error, or it could even make demons fly out of your nose.
You are reading into c but printing i, so you will see 01234. You probably mean to print c. But that's not enough. c should be declared int because you are reading with format "%d", which expects an int. Either use format hhd or change c to type int
scanf("%d",&c);
should be
scanf("%c",&c);
btw. It will ask you to input value for c in every iteration and then it will print one value of i. What are you getting?
What's the reason of the strange output?
It's because you havn't used scanf properly. When you use "%d", you have to give scanf a pointer to an int, but you gave it a pointer to a char.
Change your char c to int c
(You should also check functions for errors. e.g. scanf will return EOF on end of input. It will also return the count of assigned values. Since you have given it 1 value, &c , you should check that scanf returns 1. If it does not, something bad might have happened)

Resources