2

Happy new year everyone.

I am studying C language. I had a question when some code run about pointer.

#include <stdio.h>

int * b() {
    int a = 8;
    int *p = &a;
    printf("the addr of a in b: %p\n", p); the addr of a in b: 0x7ffccfcba984
    return p;
}

int main () {
    
   int *c = b();
   printf("the addr of a in main: %p\n", c); // the addr of a in main: 0x7ffccfcba984
   printf("The value of ptr is : %d\n", *c ); // 8
   
   return 0;
}

Can you feel something odd in this code?

I learned that a variables declared inside a function is deallocated at the end of the function. However, I can still access variables outside the function like above code when trying to access the address of "a" variable. If the deallocation is true, int a should be deallocated at the end of the b function. It is like a free is not used after variables is declared. Is there some knowledge I am missing about deallocation? Could you tell me why I can still access it?

Tory
  • 43
  • 3
  • How are you compiling this code? – costaparas Jan 05 '21 at 10:25
  • What did you expect to happen? Such code is Undefined Behaviour. UB does not mean "immediately stop the program". It means the exact result is unpredictable. It can sometimes appear to "work" but may show a different result under other circumstances. – kaylum Jan 05 '21 at 10:26
  • I'm using web editor. here (https://www.tutorialspoint.com/compile_c_online.php) – Tory Jan 05 '21 at 10:27
  • You should be compiling your code with at least a basic set of compilation flags. Compilers can easily warn you about this - you would get the error "function returns address of local variable". Just because the code *compiles* and even "*runs*", it doesn't make it correct. – costaparas Jan 05 '21 at 10:28
  • Read this very interesting answer: https://stackoverflow.com/a/6445794/898348. It's for C++ but it's also valid for C. – Jabberwocky Jan 05 '21 at 10:29

2 Answers2

1

Once you leave a function variables "fall out of scope" meaning they are no longer valid.

Using the address of an out of scope variable breaks that boundary and leads to undefined behaviour, as in, it's not valid to do. The &a pointer is effectively invalidated when you exit that function. If you use it then the program may behave erratically, might crash, or might work fine. It's not defined what happens.

In this trivial example you're not going to get the same behaviour as in a real program. Make another function call to a function that exercises the stack and you'll likely see some problems since the stack is being re-used.

Local variables aren't "allocated" per-se, they are simply scoped, and when that scope is exited they are invalidated.

In something like C++ there may be a deallocation process when things fall out of scope, as that language can define destructors and such, but that's not the same as C. In C they just cease to exist.

tadman
  • 208,517
  • 23
  • 234
  • 262
  • Re “*undefined behaviour*, as in, it's not valid to do”: That is completely wrong. The C standard was not written to define a single language for which every program is portable to every implementation. It was designed to give a common core in which the language itself, not just programs, could be adjusted to work on different platforms, such as some that had 16-bit `int`, some that had 32-bit `int`, some that had one’s complement, and more. The C standard does **not** make it invalid to use its “undefined behavior” other than the constraints and run-time constraints. Rather, these… – Eric Postpischil Jan 06 '21 at 02:02
  • … are places where a C implementation may plug-in its own specification of what happens. When you buy a car with blank or empty spots in the front console, which the manufacturer has not given any function to, those are not spots you are prohibited from using. You may insert third-party devices into them and use them. Many of the “undefined behavior” spots in C are the same way: They are not prohibited but are places for new things to be installed. – Eric Postpischil Jan 06 '21 at 02:04
  • 1
    Re “Using the address of an out of scope variable breaks that boundary and leads to undefined behaviour”: This is false. Proof: `void foo(int *x) { printf("%d\n", *x); } void bar(void) { int b = 3; foo(&b); }` uses the address of `b` out of the scope of `b` but is fully defined by the C standard. This is not difficult: Scope is **where** in source code an identifier is visible. Lifetime is **when** during program execution an object exists. It is not good to mix up these terms for students. – Eric Postpischil Jan 06 '21 at 02:07
  • @EricPostpischil Fair, but I'd argue you're still "inside" the scope due to the function call, the scope hasn't ceased to exist, and in any debugger you can see that `b` still exists on the call stack. Explaining lifetimes here does complicate things, but if you think it's necessary you've added the notes. – tadman Jan 06 '21 at 02:13
0

I learned that a variables declared inside a function is deallocated at the end of the function.

If the deallocation is true, int a should be deallocated at the end of the b function.

Yes. You are not wrong.

A variable will be destructured when it goes out of its scope. Although you use a pointer variable to save a pointer to that variable, accessing it through that pointer is actually an undefined behavior.

Yes, you can access it and see the results you expect because of luck or environment, but it may still cause a crash, unexpected results, etc. Because this behavior is undefined and wrong.

Sprite
  • 3,222
  • 1
  • 12
  • 29