-1

My understanding is that as soon as testStack is invoked, a new stack frame is created and all local variables will live in that stack frame. And once stack frame is removed those local variable will also be gone.

In below program, I returned that memory location of one of the local variables created in testStack and I was able to access that variable value again in main method.

Questions:

  1. So, this is true that even though stack frame is removed but still that memory location is holding the local variable value or I am misunderstanding something.
    • Can it be potentially dangerous that local variables can be accessed like even when its stack frame is removed?
  2. In testStack local variable x was created on stack and its value was also on stack.

    • Would it had made any difference in terms of heap or stack memory if instead of int x; I had said int* x;

      string testStack();
      
      int main(void){
      string memAdd = testStack();
      printf("memAdd = %i\n", memAdd);
      printf("*memAdd = %i\n", *memAdd);
      printf("*&memAdd = %i\n", *&memAdd);
      *&memAdd = 11;
      printf("*&memAdd = %i\n", *&memAdd);
          }
      
      string testStack(){
          int x;
          printf("%i\n", x);
          printf("%i %p %p\n", x, x, &x);
          *&x = 33;
          printf("%i\n", x);
          //free(x);
          return &x;
      }
      

O/P:

134513341
134513341 0x80482bd 0xbffd9eac
33
memAdd = -1073897812
*memAdd = 33   //From main method... Stack frame of testStack() should have been removed by now...
*&memAdd = -1073897812
*&memAdd = 11
hagrawal7777
  • 14,103
  • 5
  • 40
  • 70
  • 3
    UB. It's UB. It was UB the first time this question was asked years ago. It's still UB now. – Martin James Jul 23 '15 at 18:57
  • Yes, undefined behavior is potentially dangerous. – John Coleman Jul 23 '15 at 19:00
  • 1
    possible duplicate of [Pointer to local variable](http://stackoverflow.com/questions/4570366/pointer-to-local-variable) – Martin James Jul 23 '15 at 19:00
  • 1
    or http://stackoverflow.com/questions/4824342/returning-a-local-variable-from-function-in-c – Martin James Jul 23 '15 at 19:05
  • 1
    …and many more. Why don't you do research before asking? – The Paramagnetic Croissant Jul 23 '15 at 20:16
  • @MartinJames Thank you for your inputs. I got that it will be undefined behavior but see this accepted answer from http://stackoverflow.com/questions/4824342/returning-a-local-variable-from-function-in-c "*The issue here is that when you create the local variable it is allocated on the stack and is therefore unavailable once the function finishes execution (implementation varies here). *" And this is what my question is, clearly I was able to see the local variable of previous method even though it was removed. To be continued below ... – hagrawal7777 Jul 23 '15 at 22:02
  • Now there could be 2 possibilities - (1.) The stack memory was still holding the data and that stack memory location was not cleared. (2.) As @user1666959 suggested, that it might have done into register, but then I am wondering how I was able to get the value. – hagrawal7777 Jul 23 '15 at 22:02
  • @TheParamagneticCroissant It is touching the same concept but did you read the questions completely? Which previous question is answering this - "*Can it be potentially dangerous that local variables can be accessed like even when its stack frame is removed?*" – hagrawal7777 Jul 24 '15 at 10:36
  • @hagrawal The very first duplicate linked by Martin James states that it's undefined behavior. Which means that yes, it's potentially dangerous. – The Paramagnetic Croissant Jul 24 '15 at 10:51

2 Answers2

2

Others have more or less answered your questions. Here is some more detail:

1."My understanding is that as soon as testStack is invoked, a new stack frame is created and all local variables will live in that stack frame"

There is no guarantee that a stack frame will be created. The compiler may decide to pass all arguments in registers and may keep all locals in registers. This is likely to happen on CPUs where there are plenty of registers and for functions with few locals.

  1. "Would it have made any difference...?"

a. in terms of heap: standard terminology is that heap is what is not code or stack (and not space reserved for globals), you allocate from it via malloc(). The stack normally grows in opposite direction to the heap, so when you push something on the stack you have less heap space left. If an argument is passed in registers and locals are also in registers then the snippet will use less stack/heap space..ie there is no need to store those variables.

b. int x vs int* x: x is just a local variable inside, I can't think of any circumstances when its type would make a difference (with the exception where the size of an int (in bits) is different from the size of a pointer. A decent compiler might cater for such architectures, maybe the ARM in thumb mode?). So if the compiler decides (perhaps the function is small, called frequently, inlineable) that the local will be kept in a register then no stack frame will ever be created.

user1666959
  • 1,805
  • 12
  • 11
1

On the x86 platform removing shack frame happens by the increasing esp register and restoring ebp register from the stack. Until the next procedure call your stack memory is not touched and you could access it. But other platform could handle these things differently so accessing memory from the deleted stack frame is undefined behavior.

Edit: 1) Would it be any different if you used pointer instead? Well, thats depends. If you allocate data on the heap (using for example new operator) and then return pointer from your procedure - this is completely valid technique. Otherwise its pretty much the same.

2) Can it be potentially dangerous? Well, you have to clarify about kind of danger we actually speaking here. Is it valid programming approach? Of course not. This is UB. Is this a potential security leak? Yes, perhaps. You could not expect guaranteed stack frame memory cleanup from the compiler, you have to do it yourself using special methods.

Ari0nhh
  • 5,720
  • 3
  • 28
  • 33