Reputation:
(Sorry for bad English.)
Question 1.
void foo(void)
{
goto inside;
for (;;) {
int stack_var = 42;
inside:
...
}
}
Will be a place in stack allocated for the stack_var
when I goto the inside
label? I.e. can I correctly use the stack_var
variable within ...
?
Question 2.
void foo(void)
{
for (;;) {
int stack_var = 42;
...
goto outside;
}
outside:
...
}
Will be a place in stack of the stack_var
deallocated when I goto the outside
label? E.g. is it correct to do return
within ...
?
In other words, is goto
smart for correct working with stack variables (automatic (de)allocation when I walk through blocks), or it's just a stupid jump?
Upvotes: 11
Views: 452
Reputation: 80325
can I correctly use the stack_var variable within ...?
The code in ... can write to stack_var
. However, this variable is uninitialized because the execution flow jumped over the initialization, so the code should not read from it without having written to it first.
From the C99 standard, 6.8:3
The initializers of objects that have automatic storage duration […] are evaluated and the values are stored in the objects (including storing an indeterminate value in objects without an initializer) each time the declaration is reached in the order of execution
My compiler compiles the function below to a piece of assembly that sometimes returns the uninitialized contents of x
:
int f(int c){
if (c) goto L;
int x = 42;
L:
return x;
}
cmpl $0, %eax
jne LBB1_2
movl $42, -16(%rbp)
LBB1_2:
movl -16(%rbp), %eax
...
popq %rbp
ret
Will be a place in stack of the stack_var deallocated when I goto the outside label?
Yes, you can expect the memory reserved for stack_var
to be reclaimed as soon as the variable goes out of scope.
Upvotes: 10
Reputation: 1
There are two different issues:
lexical scoping of variables inside C code. A C variable only makes sense inside the block in which it is declared. You could imagine that the compiler is renaming variables to unique names, which have sense only inside the scope block.
call frames in the generated code. A good optimizing compiler usually allocate the call frame of the current function on the machine class stack at the beginning of the function. A given location in that call frame, called a slot can (and usually is) reused by the compiler for several local variables (or other purposes).
And a local variable can be kept in a register only (without any slot in the call frame), and that register will obviously be reused for various purposes.
You are probably hurting undefined behavior for your first case. After the goto inside
the stack_var
is uninitialized.
I suggest you to compile with gcc -Wall
and to improve the code till no warnings are given.
Upvotes: 2