3 ms·
> If you write a goto which goes around these encapsulated scopes, that goto does not jump into a region where the variable is uninitialized. That's true when
by trealira 3y ago
> If you write a goto which goes around these encapsulated scopes, that goto does not jump into a region where the variable is uninitialized.
That's true when you write a goto that goes around scopes, and doesn't jump into them. However, you can still jump into the middle of an inner scope, where sometimes a variable might be uninitialized.
void c89_fn(int arg) {
if (arg > 0)
goto after;
{
int x = 42; /* or "int x; x = 42;" */
after:
/* x is in scope, but x could be uninitialized */
printf("%d\n", x);
}
}
For this particular example, GCC and Clang inline the definition of x as 42 unconditionally with any amount of optimizations on, but with -O0, both generate code that reads from a sometimes-uninitialized stack address. There's probably a more practical example that one could find.
- kazinator 3y agoThe point is that your goto cannot avoid this, if your local variable scopes close at the end of the function, due to not using nested blocks. If you jump around those variables, you're jumping into a region where they are still visible and not inited. Also, my original example is invalid C++, as is yours. C++ does not allow goto to skip variable initializations. In C++, if you want to goto past some variable declarations, you have to do the right thing and encapsulate them into a block. GCC's diagnostics look like: goto.cc: In function ‘void f()’: goto.cc:7:1: error: jump to label ‘end’ [-fpermissive] end:; ^~~ goto.cc:3:8: note: from here goto end; ^~~ goto.cc:5:7: note: crosses initialization of ‘int x’ int x = 42; ^
- trealira 3y ago> The point is that your goto cannot avoid this, if your local variable scopes close at the end of the function, due to not using nested blocks. If you jump around those variables, you're jumping into a region where they are still visible and not inited. I see. I think I get what you're saying: if you only put variable declarations at the top of the scope, then if you only jump to labels at the same statement depth as the goto statement, you won't skip initialization or assignment of uninitialized variables. Whereas, if you mix declarations and statements, you might end up with uninitialized variables even when you only jump to labels at the same statement depth as the goto statement. Is that what you're saying, or did I grasp something orthogonal to your point? > C++ does not allow goto to skip variable initializations. I didn't know that until now. However, if you change the function so that x is assigned after being declared, it still compiles and produces the same result. void c89_fn(int arg) { if (arg > 0) goto after; { int x; x = 42; after: /* x is in scope, but x could be uninitialized */ printf("%d\n", x); } }