Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

setting pointer to variable declared in local scope in C

I have a question about scoping rules in C that can best be illustrated by the following code:

#include <stdio.h>

int main(void)
{
    int * x = NULL;

    {
        int y = 42;
        x = &y;
        printf("%d\n", *x);
    }

    printf("%d\n", *x);
    *x = 74;
    printf("%d\n", *x);

    return 0;
}

Running this code prints out

42
42
74

I've compiled it using clang with all warnings and with -fsanitize=undefined.

The variable y is declared in a local scope, and is inaccessible after the closing brace. Nonetheless, we can make a previously-declared pointer refer to that local variable, and we can refer to the contents of that memory even after its scope ends.

While this code might work due to the peculiarities of how the program stack works on my machine, it seems to me that dereferencing x at this point should be undefined behavior. I have a better feel for how I'd answer this question in C++. If we were using some class with a non-trivial destructor, rather than a basic type like int, then its destructor will be called at the closing brace.

Does this code invoke undefined behavior? I don't know the C standard very well, so a citation on the relevant rule would be appreciated.

like image 579
Daniel Shapero Avatar asked Mar 26 '26 19:03

Daniel Shapero


2 Answers

Yes, this is undefined behavior. From §6.2.4 2 of the C11 Standard:

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.

The variable y has automatic storage duration in the posted code. From §6.2.4 5:

An object whose identifier is declared with no linkage and without the storage-class specifier static has automatic storage duration....

The very next paragraph states that:

For such an object 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.

So the lifetime of y ends after execution of the enclosing block completes, at which time the value of the pointer x becomes indeterminate, and it is undefined behavior to attempt further access of y through x or any other means.

like image 152
ad absurdum Avatar answered Mar 29 '26 00:03

ad absurdum


From N1570:

6.2.4.2:

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.

6.2.4.5:

An object whose identifier is declared with no linkage and without the storage-class specifier static has automatic storage duration, as do some compound literals.

6.2.4.6:

For such an object 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.

Whoops! Dragons.

like image 26
Quentin Avatar answered Mar 29 '26 01:03

Quentin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!