Park Park - 1 month ago 18
C Question

initializing local variables, when does it happen?

I just learned about local variables in C and a book said that a local variable always initialized itself from memory when the function having local variable ends.
So I just wrote some code (with Visual Studio 2015) to confirm that.
Here is the code:

#include <stdio.h>
int* poin2 = NULL;
void fuc(void);

int main(void) {
int a = 3;

fuc();

printf("%d %d\n", a, *poin2);

return 0;
}

void fuc(void)
{
int a = 2;
poin2 = &a;
}


At first, I thought it would show 3 and a garbage number because fuc is over, a in fuc (not in main) must be initialized in memory, so poin2 means nothing.
but the result is:

3 2


Why isn't it removed from memory? I tested the next code to figure out:

#include <stdio.h>
int* poin2 = NULL;
void fuc(void);

int main(void) {
int a = 3;
int b = 1;
fuc();
while (1)
{
b++;
printf("%d %d\n", a, *poin2);
if (b > 5) break;
}

return 0;
}

void fuc(void)
{
int a = 2;
poin2 = &a;
}


What I thought is: initializing memory takes a short time, so I wanna find just when. The result:

3 2
3 -858993460
3 -858993460
3 -858993460
3 -858993460


I tested it with some more code, and I figured out that it changed not when a function having local variable finished, just when another function finished.
(I mean it doesn't removed when fuc() finished, it removed when printf finished,
and it doesn't depend on what function is, not only printf, but also scanf or other else)

But why? Is it wrong in my code or something?

Answer

As you may be aware, returning the address of a local variable and then attempting to dereference that address is undefined behavior.

What that means is that your program could crash, it could exhibit strange behavior, or it could appear to work properly. This behavior does not need to be consistent from one compiler to the next for the same code or in the presence of a seeming unrelated change.

That being said, many compilers typically won't modify the portion of the stack used by a function after it returns. It's extra work that usually isn't needed. So immediately after fuc returns, the local variables it has still contain their old values.

On the call to printf, the pointer poin2 is dereferenced before printf is called. Since no other functions were called prior to this happening, the value of a from the last call to func has not yet been overwritten. So you read the old value.

When you call printf in a loop, the first call is able to get the value of a as before. However, calling printf then modifies the stack. Specifically, the memory location where a was stored is overwritten with something else. So on subsequent calls to printf it reads whatever the last call to printf left in that memory location.

To reiterate however, this is undefined behavior. Not all compilers are required to behave in this fashion. For example, in a high security environment a compiler might clear out stack memory after a function returns so that sensitive data used by that function cannot be recovered.