4

Local variables exists at least (and at most) inside functions. However, what happens to block-scope variables outside block but it the same function, could I keep and use their address? Is this code valid?

#include <stdio.h>

int main()
{
   char *f;
   if (1)
   {
       char q[] = "123";
       f = q;   
   }

   printf ("%s\n", f);   
   return 0;
}

In fact neither gcc -ansi -pedantic nor valgrind complain on it, but could I use it cross-platform and cross-compiler? Seems to me no, but what tool could show me the error?

P.S. Should I use static after all? It could be appropriate solution, but it seems to me not a thread safe one?

Nick
  • 970
  • 10
  • 20
  • 3
    That duplicate isn't a very good answer here. The question is about scope within a function not passing back from another function. While equally invalid there are more subtle reasons why the example in this question is invalid than simply returning pointers to an expired stack-frame. – Persixty Apr 18 '17 at 09:05

1 Answers1

9

No you cannot. Variables with automatic storage duration have their lifetime set to the enclosing block. What you end up with is a dangling reference, and using that is undefined behavior.

[C11 §6.2.4 ¶2]

The lifetime of an object is the portion of program execution during which storage is guaranteed to be reserved for it. An object exists, has a constant address,33) and retains its last-stored value throughout its lifetime.34) If an object is referred to outside of its lifetime, the behavior is undefined. The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.

[C11 §6.2.4 ¶6]

For such an object (with automatic storage duration) that does not have a variable length array type, its lifetime extends from entry into the block with which it is associated until execution of that block ends in any way.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • 1
    I checked this code on my machine and the output was "123". Saying it's UB means that the PC can replace that data (and change permissions accordingly) with whatever it likes? – CIsForCookies Apr 18 '17 at 09:01
  • 2
    @CIsForCookies - Saying it's undefined behavior means the C standard makes no requirement on compilers to produce consistently correct code, or even correct code to begin with. – StoryTeller - Unslander Monica Apr 18 '17 at 09:02
  • 1
    @CIsForCookies it is UB because "123" is placed on the stack as a local variable. When the scope finishes the stack pointer changes its position without clearing the not-used-anymore stack because it would be a waste of CPU time. UB appears when you call a different function reusing this stack where "123" is (but is unused). That is why local variables (and pointers) should be initialized. – Rogus Apr 18 '17 at 09:03
  • Thanks, I understand about UB, but I still wonder why no complain of gcc, valgrind (and cppcheck, btw). – Nick Apr 18 '17 at 09:14
  • @Nick - UB means all bets are off, and depending on platform it may seem to work, or fail horribly. A code sample, almost exactly like the one you posted, crashed in my shop when we started building on a new target Arch/OS combo with GCC. I'll see if I can find more details for you (the specifics elude me at the moment). – StoryTeller - Unslander Monica Apr 18 '17 at 09:18
  • @StoryTeller `No you cannot.` This is a bad Answer :)). Of course you can, but is UB. This was my point :D – Michi Apr 18 '17 at 09:33
  • @Michi - I could say "should not" instead. But IMHO there should be left no doubt that UB is bad bad bad. – StoryTeller - Unslander Monica Apr 18 '17 at 09:34
  • @StoryTeller You're right :) – Michi Apr 18 '17 at 09:35