can someone explain this to me
main()
{
int *x,y;
*x = 1;
y = *x;
printf("%d",y);
}
when I compile it in gcc how come running this in main function is ok, while running it in different function wont work like the function below?
test()
{
int *x,y;
*x = 1;
y = *x;
printf("%d",y);
}
int *x,y;
*x = 1;
Undefined Behavior. x doesn't point to anything meaningful.
This will be correct:
int *x, y, z;
x = &z;
*x = 1;
y = *x;
or
int *x, y;
x = malloc(sizeof(int));
*x = 1;
y = *x;
//print
free(x);
Undefined behavior is, well, undefined. You can't know how it will behave. It can seem to work, crash, print unpredictable results and anything else. Or it can behave differently on different runs. Don't rely on undefined behavior
Technically, in standardese, you invoke what is called undefined behavior due to using an uninitialized value (the value of the pointer x).
What's going on under the hood is very likely this: your compiler allocates local variables on the stack. Calling functions likely changes the stack pointer, so different function's local variables are at different places on the stack. This in turn makes the value of the uninitialized x be whatever happens to be at that place in the current stack frame. This value can be different, depending on the depth of the chain of functions you called. The actual value can depend on a lot of things, e.g. back to the whole history of processes called before your program started. There's no point in speculating what the actual value might be and what kind of erroneous behavior might possibly ensue. In the C community we refer to undefined behaviour as even having the possibility to make demons fly out of your nose. It might even start WW3 (assuming appropriate hardware is installed).
Seriously, a C programmer worth her money will take extreme care not to invoke undefined behavior.
since x is a pointer, its not containing the int itself, it points to another memory location which holds that value.
I think you assume that declaring a pointer to a value also reserves memory for it... not in C.
If you made the above error in your code, maybe it would be good if I gave you a little bit more graphic representation of what is actually going on in the code... this is a common novice error. The explanation below might seem a bit verbose and basic, but it might help your brain "see" what is actually going on.
Let's begin... if [xxxx] is a value being stored in a few bits in the RAM, and [????] is an unknown value (in physical ram) you can say that that for X to be properly used it should be:
x == [xxxx] -> [xxxx]
x == address of a value (int)
when you write: *x=1 above, you are changing the value of an unknown area of RAM, so you are in fact doing:
x == [????] -> [0001] // address [????] is completely undefined !
In fact, we don't even know IF address [????] is allocated or accessible by your application (this is the undefined part), its possible the address points to anything. Function code, dll address, file handle structure... it all depends on the compiler/OS/application state, and can never be relied on.
so to be able to use a pointer to an int, we must first allocate memory for it, and assign the address of that memory to x, ex:
int y; // allocate on the stack
x = &y; // & operator means, *address* of"
or
x = malloc(sizeof(int)); // in 'heap' memory (often called dynamic memory allocation)
// here malloc() returns the *address* of a memory space which is at least large enough
// to store an int, and is known to be reserved for your application.
at this point, we know that x holds a proper memory address so we'll just say it's currently set to [3948] (and contains an unknown value).
x == [3948] -> [????]
Using the * operator, you dereference the pointer address (i.e. look it up), to store a value AT that address.
*x = 1;
means:
x == [3948] -> [0001]
I hope this helps
Related
I am not clear for how long a variable is guaranteed to be allocated in C.
For example, if I have:
void foo(void) {
int x;
int* y = &x;
...
}
Is the space allocated on the stack for x guaranteed to be reserved for this variable exclusively for the entire duration of foo()? Said differently, is y guaranteed to point to a location that will be preserved for the entire duration of foo, or could the compiler decide that since x isn't being used, the stack space can be used for another use within foo and therefore *y may change without accessing y (or x) directly?
When you ask questions like this, you should be clear whether you are asking about C semantics or about program implementation.
C semantics are described using a model of an abstract computer in which all operations are performed as the C standard describes them. When a compiler compiles a program, it can change how the program is implemented as long as it gets the same results. (The results that must be correct are the observable behavior of the program: its output, including data written to files, its input/output interactions, and its accesses to volatile objects.)
In the abstract computer, memory for x is reserved from the time an execution of foo starts until that execution of foo ends.1, 2
So, in the abstract computer, it does not matter if x is used or not; memory is reserved for it until foo returns or its execution is ended in some other way (such as a longjmp or program termination).
When the compiler implements this program, it is allowed optimize away x completely (if it and its address are not used in any way that requires the memory to be reserved) or to use the same memory for x that it uses for other things, as long as the uses do not conflict in ways that change the observable behavior. For example, if we have this code:
int x;
int *y = &x;
x = 3;
printf("%d\n", x);
int b = 4;
printf("%d\n", b);
then the compiler may use the same memory for b that it uses for x.
On the other hand, if we have this code:
int x;
int *y = x;
printf("%p\n", (void *) y);
int b = 4;
printf("%p\n", (void *) &b);
then the program must print different values for the two printf statements. This is because different objects that both exist at the same moment in the abstract computer model must have different addresses. The abstract computer would print different addresses for these, so the compiler must generate a program that is faithful to that model.
Footnotes
1 There can be multiple executions of a function live at one time, due to nested function calls.
2 Sometimes people say the lifetime of x is the scope of the function, but this is incorrect. The function could call another routine and pass it y, which has the address of x. Then the other routine can access x using this address. The memory is still reserved for x even though it is not in the scope of the other routine’s source code. During the subroutine call, the execution of foo is temporarily suspended, but it is not ended, so the lifetime of x has not ended.
The lifetime of an automatic variable is the entire duration of the scope in which it is declared; in your case, that scope is the whole of the foo function.
Compilers are allowed to make optimizations (including removing variables completely) that can have no possible observable effect; however, once you assign the address of x to y, then any use of *y will be using x, so the memory allocated for x cannot then be used for something else, all the time there is a possibility of accessing or modifying *y.
x is being used, y is being passed the address of it! In short the answer is "yes" as long as the compiler author(s) is(are) sensible. Most compilers ( visual studio at least ) wouldn't compile this or at least warn that x is uninitialized so this isn't a very realistic example.
Y most definitely cannot change by changing another variable than x or y. that's 100%. When you go into a function the parameters then the local variables are pushed onto the stack and then when you come out of a function they are popped off. There is no scope for shared memory (unless you are using a union).
Whats the reason behind this question? If you really want to know how c is defined you should read "The C Programming Language" by Kernighan and Ritchie"
this is the code :
#include <stdio.h>
#include <stdlib.h>
int main() {
int a = 10;
int b = 20;
//printf("\n&a value %p", &a);
int* x = &b;
x = x + 1;
*x = 5;
printf("\nb value %d", b);
printf("\na value %d", a);
}
I want override a with b adress for test the c overflow but when I comment the line 5(printf fuction) I can't write five in a. While if I print the a adress I can write five in a.
Why?
Sorry for my english and thank you.
The reason this occurred is that all normal compilers store objects with automatic storage duration (objects declared inside a block that are not static or extern) on a stack. Your compiler “pushed” a onto the stack, which means it wrote a to the memory location where the stack pointer was pointing and then decremented the pointer. (Decrementing the pointer adds to the stack, because the stack grows in the direction of decreasing memory addresses. Stacks can be oriented in the other direction, but the behavior you observed strongly suggests your system uses the common direction of growing downward.) Then your compiler pushed b onto the stack. So b ended up at a memory address just below a.
When you took the address of b and added one, that produced the memory address where a is. When you used that address to assign 5, that value was written to where a is.
None of this behavior is defined by the C standard. It is a consequence of the particular compiler you used and the switches you compiled with.
You probably compiled with little or no optimization. With optimization turned on, many compilers would simplify the code by removing unnecessary steps (essentially replacing them with shortcuts), so that 20 and 10 are not actually stored on the stack. A possible result with optimization is that “20” and “10” are printed, and your assignment to *x has no effect. However, the C standard does not say what the behavior must be when you use *x in this way, so the results are determined only by the particular compiler you are using, along with the input switches you give it.
After x = x + 1;, x contains an address that you do not own. And by doing *x = 5; you are trying to write to some location that might not be accessible to you. Thus causing UB. Nothing more can be reasoned about.
When I run this code gcc gives me the output 10.
Can someone explain to me why it gives me 10? :)
#include <stdio.h>
int f(int x) {
int y;
y = 2*x;
}
int g() {
int z;
return z;
}
int main() {
int x=5;
f(x);
printf("%d\n",g());
}
this is undefined behavior - you are referencing a variable which has no value set to it. likely, it gives 10 because the compiler has used the same memory location for the variable in f(), but there is no guarantee of that, it should not be depended on, and is nothing more than a curiosity.
There's nothing to explain. Your code exhibits undefined behaviour on two separate, unrelated occasions: First f isn't returning anything despite being declared as returning int, and second because g returns an uninitialized value.
Practically, the way the functions will be put on the call stack will have caused the local y (which eventually has the value 10) to be in the same place as the return value of g() in the printf call, so you happen to see the value 10. But that's more or less a matter of luck.
Here:
int g() {
int z;
return z;
}
This reads:
int g():
reserve memory for an integer, call it z.
return whatever is in that reserved memory.
You never used that reserved memory for your integer. Its value is whatever was at that address before you chose to use it (or not use it, rather). That value could be anything.
You do the same in your other function. What you are doing is reading uninitialized memory. You can google that up for further information. See also the "stack" and the "heap", dynamic memory, and other related topics.
g returns an unitialized varable from the stack, in your example that location was last set by the F function giving you your answer of x*2 = 10
Because you're not initializing z, and it's using the same location on the stack as y. Since you're not initializing it the old value is still there.
This is a perfect example of why people fear optimizations and when they brag about finding compiler bugs to their bosses. This code as others have alluded to will throw warnings about using uninitialized variables in g(). With your compiler settings, it is using the old value on the stack from the call to f(5). With different compiler optimization settings, it will likely have effects on how variables end up on the stack and you'll end up getting a different results when you make changes which appear unrelated. This is undefined behavior and there is no guarantees on what value will result however it is usually easy to explain by understanding the call order and how the compiler sets up the stack. If there are warnings when you're troubleshooting weird behavior like this, fix the warnings first then start asking questions about why.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Returning the address of local or temporary variable
The add function is implemented wrongly. It should return a value instead of a pointer.
Why aren't any errors when ans and *ans_ptr are printed and the program even gives correct result? I guess the variable of z is already out of scope and there should be segmentation fault.
#include <stdio.h>
int * add(int x, int y) {
int z = x + y;
int *ans_ptr = &z;
return ans_ptr;
}
int main() {
int ans = *(add(1, 2));
int *ans_ptr = add(1, 2);
printf("%d\n", *ans_ptr);
printf("%d\n", ans);
return 0;
}
The reason it 'works' is because you got lucky. Returning a pointer to a local variable is Undefined Behaviour!! You should NOT do it.
int * add(int x, int y) {
int z = x + y; //z is a local variable in this stack frame
int *ans_ptr = &z; // ans_ptr points to z
return ans_ptr;
}
// at return of function, z is destroyed, so what does ans_ptr point to? No one knows. UB results
Because C has no garbage collection, when the "z" variable goes out of scope, nothing happens to the actual memory. It is simply freed for another variable to overwrite if the compiler pleases.
Since no memory is allocated between calling "add" and printing, the value is still sitting in memory, and you can access it because you have its address. You "got lucky."
However, as Tony points out, you should NEVER do this. It will work some of the time, but as soon as your program gets more complex, you will start ending up with spurious values.
No. Your question displays a fundamental lack of understanding of how the C memory model works.
The value z is allocated at an address on the stack, in the frame which is created when control enters add(). ans_ptr is then set to this memory address and returned.
The space on the stack will be overwritten by the next function that is called, but remember that C never performs memory clean up unless explicitly told to (eg via a function like calloc()).
This means that the value in the memory location &z (from the just-vacated stack frame) is still intact in the immediately following statement, ie. the printf() statement in main().
You should never ever rely on this behaviour - as soon as you add additional code into the above it will likely break.
The answer is: this program works because you are fortunate, but it will take no time to betray, as the address you return is not reserved to you anymore and any one can use it again. Its like renting the room, making a duplicate key, releasing the room, and after you have released the room at some later time you try to enter it with a duplicate key. In this case if the room is empty and not rented to someone else then you are fortunate, otherwise it can land you in police custody (something bad), and if the lock of the room was changed you get a segfault, so you can't just trust on the duplicate key which you made without acquisition of the room.
The z is a local variable allocated in stack and its scope is as long as the particular call to the function block. You return the address of such a local variable. Once you return from the function, all the addresses local to the block (allocated in the function call stack frame) might be used for another call and be overwritten, therefore you might or might not get what you expect. Which is undefined behavior, and thus such operation is incorrect.
If you are getting correct output, then you are fortunate that the old value held by that memory location is not overwritten, but your program has access to the page in which the address lies, therefore you do not get a segmentation fault error.
A quick test shows, as the OP points out, that neither GCC 4.3 nor MSVC 10 provide any warnings. But the Clang Static Analyzer does:
ccc-analyzer -c foo.c
...
ANALYZE: foo.c add
foo.c:6:5: warning: Address of stack memory associated with local
variable 'z' returned to caller
return ans_ptr;
^ ~~~~~~~
For the following code, this is how i understand:
Reference to pointer x is passed to function f,
val get the address of y which is a local variable.
So why, after exiting function f, x is ok? y should have been dereferenced.
x is equal to 5, and both printf print the same adress.
void f (int ** val)
{
int y = 5 ;
*val = & y;
printf("%d\n", &y);
}
int _tmain(int argc, _TCHAR* argv[])
{
int * x ;
f(&x );
if ( *x == 5 )
printf("%d", x);
}
It is Undefined Behaviour to access memory your program does not own.
The memory space occupied by y inside the function does not belong to your program once the function finishes, and yet you access it.
Anything could happen.
The worst thing to happen is for the program to behave as you expect.
When this happens, you believe it is ok to do what you did. IT IS NOT OK. Undefined Behaviour is bad.
Also it's not guaranteed that the same undefined behaviour happens on different runs of the program either. It can work as you expect for a while and crash when you demo it to the client (or your boss).
(Some good manifestations of UB are a crash, or lemon juice starting to ooze out of the USB port)
Anything can happen.
x is pointing to a local variable inside f which is no longer valid by the time f returns.
EDIT: Your post doesn't make it clear what you expect should happen, but as described much clearer in other answers, *x is pointing to memory which you do not own, and reading from *x is undefined behavior, so all bets are off. If you try to read from *x and it happens to be 5, it is probably because the value of 5 is still on the stack. Try to insert some calls to printf immediately after the call to f, and you will probably get another result.
The y variable sits on the stack. so you pass an address on the stack to x, and it's a valid address, but with undefined content. if you add another function (like printf) between the call to f and the check of *x == 5 you'll probably get a different result (since the stack was changed).
This is a classic...
The variable y is only alive as long as the function f is executed. Once it returns, the memory space occupied by y on the stack can be used for anything else.
y lives only within f(int**val), since it is declared in that scope.
Refering to its address outside of f() has no clear definition (or as we love to to say: Undefined Behaviour.
Because y might not be valid, but it's value is still in memory.
It'll get nasty if you call some other function or do something else which will write on it.
As nearly everyone has already said, it's undefined behavior. The reason you are printing the correct value (5) is because your program hasn't reused that memory, yet. Wait until your program puts something else at that address, then you will see incorrect results.