2

(I believe this question is technically distinct from Can a local variable's memory be accessed outside its scope? because it is C instead of C++.)

I know that in C you can put a local variable in a block and it will be scoped to that block:

#include <stdio.h>
int main() {
    {
        int x = 5;
        printf("x = '%d'\n", x);
    }
    // can't see x anymore
}

My question is, is it nonetheless still SAFE to use that memory until the end of the function? Whether it is WISE from a design / coding practices perspective is a separate question, but is it undefined behavior or can I count on that memory staying put? For example:

#include <stdio.h>
int main() {
    int *ptr;

    {
        int x = 5;
        printf("x = '%d'\n", x);

        // hold on to a ptr while we still know the address
        ptr = &x;
    }

    // can't see x anymore, but is this safe?
    printf("still have a ptr! '%d'\n", *ptr);
}

Thanks!

Community
  • 1
  • 1
murftown
  • 1,287
  • 1
  • 10
  • 13

4 Answers4

2

Is it nonetheless still SAFE to use that memory until the end of the function?

No, it is not. Once the variable is out of scope, any reference to the memory that it once occupied is undefined behavior.

Here is a short demo with UB happening when the compiler reuses memory allocated inside a block:

int *ptr1, *ptr2;
{
    int x[8];
    scanf("%d", x);
    printf("You entered x=%d\n", x[0]);
    ptr1 = x;
}
{
    int y[8];
    scanf("%d", y);
    printf("You entered y=%d\n", y[0]);
    ptr2 = y;
}
printf("Now x=%d\n", *ptr1); // <<== Undefined behavior!!!
printf("Now y=%d\n", *ptr2); // <<== Undefined behavior!!!

I made an array because the compiler used for the demo chooses to not reuse memory of individual variables and smaller arrays. Once a certain threshold is crossed, however, the memory is reused.

Demo.

This demo shows how the address of int x[8] is reused for int y[8].

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • That's a good example, though on my mac with clang it doesn't do that, the 2 values are preserved. I see that it is not safe across architectures/compilers though. Thanks! – murftown Sep 16 '16 at 13:02
  • @murftown Try increasing the size of the array. At some point, I think, the compiler should start re-using the memory. – Sergey Kalinichenko Sep 16 '16 at 13:08
  • I kept increasing the size and couldn't see that behavior. I got a Stack Overflow instead once my arrays were 8M ;) – murftown Sep 16 '16 at 13:19
  • 1
    @murftown: "Undefined behavior" doesn't mean it won't work. It doesn't mean it will work either. It might work on every 3rd Sunday of the month on a full Moon, and crash the Moon into the Earth otherwise, as far as the C standard is concerned. More importantly (in this case), the behavior can change between compiler vendors, compiler releases (as optimization algorithms get changed and/or bugs get fixed), environment variables, optimization options, operating systems, CPU architecture, and who knows what else. It can also give different results each time it's executed. – Tim Čas Sep 16 '16 at 20:27
2

The C99, 6.2.4 p2 standard says:

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 reaches the end of its lifetime.

Rahul Tripathi
  • 168,305
  • 31
  • 280
  • 331
1

You cannot safely look at what that pointer points to, once you're outside the block, exactly as you suspect.

The "memory location" that was used for the value of X, of course, lives on, so something is likely to be there. But accessing it has no guaranteed safe result; you're likely to see garbage, and in extreme cases it might even crash the program. (And for some amount of time, you might find that the original value of X is still present! That's a red herring; it doesn't make it OK to use.)

Ben Zotto
  • 70,108
  • 23
  • 141
  • 204
  • Right, that makes sense. I was somewhat hoping C would guarantee to leave that spot alone so I could have Javascript-style "private" variables. But the compiler having the chance of recycling the local memory is good too, so good to know! – murftown Sep 16 '16 at 12:59
  • Right. But there are loads of kosher ways to keep information around outside of a scope, depending on what you're trying to do. Ask a new question here and you'll get lots of ideas-- people on SO love old school C questions. :) – Ben Zotto Sep 16 '16 at 13:00
0

It's undefined behavior. It may work on some architectures or operating systems, but don't count on it. An example of where it may work is Linux, with the red zone enabled.

owacoder
  • 4,815
  • 20
  • 47