0

I was taught that variables within scope are destroyed (freed/de-allocated?) at the instruction generated by the "}" at the end of a scope body. I was about to teach someone the same thing, but I decided to see for myself, what will happen if I change a local variable through a pointer like this:

int main ()
{
    int* p = NULL;

    if(1)
    {
        int localvar = 1;
        p = &localvar;
    }

    (*p) = 345;

    printf("%i\n", *p);

    return 0;
}

Compiled with MinGW-GCC and "-Wall -g -pedantic -w -Wfatal-errors -Wextra" (even though -Wall overrides most flags)

It was very surprising to me that not only a warning was generated, but also no runtime exception was thrown. Instead, everything seems to work just as if I am accessing a global variable.

Can this be explained in a definitive manner to avoid any future misconceptions?

Edenia
  • 2,312
  • 1
  • 16
  • 33
  • `-w` inhibits all warnings. I'm not sure how it interacts with `-Wall`, but that seems counter-productive to me. – Quentin Jun 24 '22 at 14:15
  • Does this answer your question? [What is a dangling pointer?](https://stackoverflow.com/questions/17997228/what-is-a-dangling-pointer) – Erel Jun 24 '22 at 14:16
  • You can use AddressSanitizer to catch undefined behavior like this it a fair bit of the time. https://godbolt.org/z/chsso71zr – Retired Ninja Jun 24 '22 at 14:17
  • I am just surprised that de-referencing unmapped memory region doesn't yield an access violation. – Edenia Jun 24 '22 at 14:17
  • So that's one of those cases of U/B that look like nothing bad happens? That's the most evil one huh – Edenia Jun 24 '22 at 14:18
  • Perhaps nothing bad happens in this case. Use a different compiler, different compile settings, or run the program on Tuesday and it might. Since it's a local variable the pointer points to the stack so it's unlikely to crash but you could corrupt other data that was stored at that location in a more complex program where you held onto the pointer longer. *shrug* – Retired Ninja Jun 24 '22 at 14:21
  • @Edenia if it doesn't yield an access violation, then it is not de-referencing unmapped memory ;) - the stack of the program is still there, but you are accessing an invalid area of it. – Marco Bonelli Jun 24 '22 at 14:21
  • I thought accessing an invalid area of it would result in an exception. It surely does in other compilers. Hah, I almost got fooled! thank you all :) – Edenia Jun 24 '22 at 14:24
  • @Edenia yeah, that's a symptom of Undefined Behavior: some compilers do A, others do B. – Marco Bonelli Jun 24 '22 at 14:24

1 Answers1

1

C compilers aren't required to generate an error when you do something like this. That's part of what makes C fast.

That also means that if you do something you're not supposed to do, you can trigger undefined behavior. This essentially means that no guarantees can be made regarding what the program will do. It could crash, it could output strange results, or it could appear to be work properly as in your case.

How UB manifests itself can change by making a seemingly unrelated change, such as adding an unused local variable or a call to printf for debugging.

In this particular case the memory in question hasn't been reserved for some other use so it is still in the valid memory space for the program and hasn't yet been overwritten. But again, you can't rely on that behavior.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • Why is this U/B and doesn't signal a segfault? I think it pretty much every other instances it would. – Edenia Jun 24 '22 at 14:20
  • @Edenia https://stackoverflow.com/questions/2397984/undefined-unspecified-and-implementation-defined-behavior – Marco Bonelli Jun 24 '22 at 14:21
  • Absolutely horrifying that I could do that without being hated by the compiler and OS. That's why I loved C in the first place but... still horrifying – Edenia Jun 24 '22 at 14:25
  • The lesson is that you can't test your understanding of UB by seeing if the compiler issues a diagnostic or the program crashes, because neither are required. You just have to not write code with UB in the first place. – Useless Jun 24 '22 at 14:27
  • Yep, I just wrongly thought that OS always fires a segfault in such cases and got a little fooled when it didn't. – Edenia Jun 24 '22 at 14:28
  • 1
    @Edenia yep, C will hand you a gun and tell you not to shoot yourself in the foot, but won't stop you from doing it. – dbush Jun 24 '22 at 14:28
  • In this case I shot myself in the foot, but I expected at least bleeding hah – Edenia Jun 24 '22 at 14:29
  • 1
    Probably severed pain receptor nerves and cautarized blood vessels. No bleeding, no pain - but also no foot anymore. Must have been a big gun. – Yunnosch Jun 24 '22 at 14:34