2

If I have the following code:

void bar(){
    int x = 1;
    foo();
}

void foo(){
    while(true);
}

What happens to the memory int x used in bar() when foo() is called? Is it freed? I know that the memory is freed if the function returns, however in this case the function simply never returns.

If I used this code, in which bar calls foo which, in turn, calls bar and so on, would the program eventually run out of memory, or would the old instances of the functions be replaced by the new ones?

void bar(){
    int x = 1;
    foo();
}

void foo(){
    int y = 1;
    bar();
}
NobodyNada
  • 7,529
  • 6
  • 44
  • 51
DividedByZero
  • 4,333
  • 2
  • 19
  • 33
  • 4
    It is not legal C++ to call `main` from your program. – PaulMcKenzie Mar 07 '16 at 20:29
  • 1. memory is not freed 2. program will crash with stack overflow error. 3. it will take 30 seconds to validate this, it takes several minutes to write this question – Iłya Bursov Mar 07 '16 at 20:30
  • Why would new calls to functions replace old calls? That would make recursivity unusable. – AntonH Mar 07 '16 at 20:30
  • 3
    That's exactly what a stack overflow is. – SLaks Mar 07 '16 at 20:31
  • 3
    Local variables go on the stack, along with information about the caller. Infinite recursion will eventually result in a stack overflow. Technically, your #2 is tail recursion, which could be implemented such that it just ran forever instead of running out of stack space, but that's a rare optimization in compiled languages. – Donnie Mar 07 '16 at 20:31
  • 1
    @PaulMcKenzie, it is totally legal C++ to call main from your program. It's just another function. – vy32 Mar 07 '16 at 20:33
  • I see you have some cryptography projects in your profile. Considering that you don't even seem to have learned the basics of function calls yet, I would strongly advise not trying to do any cryptographic work. Crypto is *really, really* tricky, and if you get it wrong, you'll just be silently leaking data everywhere without knowing about it. – user2357112 Mar 07 '16 at 20:33
  • 6
    @vy32: No, seriously, calling main is [explicitly forbidden](http://stackoverflow.com/questions/2128321/can-main-function-call-itself-in-c). It's not considered just another function. – user2357112 Mar 07 '16 at 20:35
  • Since `x` has automatic storage duration, it won't go away until it falls out of scope. While executing `foo`, it must still be alive, irrespective of how any given compiler implements objects with automatic storage duration. – IInspectable Mar 07 '16 at 20:36
  • @user2357112 Don't worry, my Crypto work is usually in high level, managed languages. I am not familiar with C and lower-level languages as I have never used them - The first time I used a low(er) level language was when I recently started developing a kernel. – DividedByZero Mar 07 '16 at 20:39
  • Neither `int x = 1;` nor `int y = 1;` necessarily even exist in the executable as an optimizing compiler can drop them. – chux - Reinstate Monica Mar 07 '16 at 20:45
  • @vy32 - No, you're wrong. You've just seen some crappy C++ code being accepted that does allow it. – PaulMcKenzie Mar 07 '16 at 20:45
  • @Donnie C does not specify local variables go on the stack. Nor does it specify infinite recursion will eventually result in a stack overflow. These are possible things and an implementation detail of the compiler. – chux - Reinstate Monica Mar 07 '16 at 20:49
  • I would expect calling a function like `_Noreturn void foo()` might / might not do some housekeeping and recover memory like `int x` before calling `foo()`. – chux - Reinstate Monica Mar 07 '16 at 20:57
  • @chux- Fair point. I have to admit I haven't read the spec in a really, really long time. – Donnie Mar 07 '16 at 20:58

6 Answers6

5

In this case, x is allocated on the stack. When you call function foo(), all variables stored on the stack stay allocated - the new function uses a new stack 'frame'. This is required because if your function foo() ever were to return, then it would need to be able to access variable 'x' on the old stack frame. If that new function (foo) calls another, then both will still be consuming their stack memory. If foo recursively called foo, there would be one new 'foo' stack frame (and so, stack space allocated for variable y as well) for each recursive call. If there are too many function calls that consume too much stack space (recursively or not), you will eventually run out of stack space, and your program will fail.

Liam Finnie
  • 169
  • 1
  • 2
  • The *base pointer* (current frame pointer) is pushed onto the stack and all variables stored on the stack stay allocated.... (which provides the address for execution to resume when the called function returns). – David C. Rankin Mar 07 '16 at 20:41
  • 4
    This answer explains a common implementation. The C++ language does not mandate the use of a stack (besides the unrelated [std::stack](http://en.cppreference.com/w/cpp/container/stack) container class template) for objects with automatic storage duration. – IInspectable Mar 07 '16 at 20:46
  • "then it would need to be able to access variable 'x' on the old stack frame. " does not apply to OP's code as `x` is not used after the function call. – chux - Reinstate Monica Mar 07 '16 at 21:21
2

What happens to the memory int x used in bar() when foo() is called? Is it freed? I know that the memory is freed if the function returns, however in this case the function simply never returns.

No, it's not freed. The x variable is freed when bar returns, which never happens in your case.

If I used this code, in which bar calls foo which, in turn, calls bar and so on, would the program eventually run out of memory, or would the old instances of the functions be replaced by the new ones?

You would eventually get stack overflow, because you never release the local variables (because you never return), and you only have a limited stack space available per thread. In windows using MSVC it's 1MB.

Jts
  • 3,447
  • 1
  • 11
  • 14
  • 2
    Not going to down vote but calling `main` from the program is undefined behavior. We can have no concrete idea of what will happen if `foo` calls `main` – NathanOliver Mar 07 '16 at 20:40
  • @NathanOliver The "calling main from program" idea was actually mine.. I edited my post after PaulMcKenzie pointed my mistake out, however most of these answers are from that time. – DividedByZero Mar 07 '16 at 20:43
  • 1
    @RandomUser Which is part of the reason I am not down voting. A lot of people seem to know know calling `main` is UB and even if it is UB most likely what they described is what will happen. I just am very hesitant to give any answer detailing what is going on when there is UB as it might not always be the case. – NathanOliver Mar 07 '16 at 20:45
2

The end condition you describe is called a stack overflow, and yes, the program would eventually run out of memory in its stack segment. Each function, when called, is allocated a space on the stack that holds the data it needs to function called a stack frame.

void f1() {
    int x;
    f2();
}

void f2() {
    int y;
    f1();
}

Calling either of these functions would result in stack frames repeatedly being allocated on the stack until it exceeded the limit designated by the operating system.

See https://en.wikipedia.org/wiki/Call_stack

Mac O'Brien
  • 2,407
  • 18
  • 22
1

The memory is held on the stack and the stack pointer moves to make room for the local variables in main(). In fact, the entire stack frame is preserved. If bar() is called again then more memory will be locked on the stack. At some point you will have a stack overflow, not to be confused with http://www.stackoverflow/.

vy32
  • 28,461
  • 37
  • 122
  • 246
1

What happens to the memory a function (bar()) uses when it calls another function (foo()) ?

The memory will stay alive if bar() may return and the memory is used after the call.

    void foo();
    void bar(){
      int x = rand();
      foo();
      printf("%d\n", x);
    }

Cases when the memory may or may not remain

    // foo() is _Noretrun, no need to keep `x`
    _Noretrun void foo();
    void bar(){
      int x = rand();
      foo();
      printf("%d\n", x);
    }

    // `x` optimized out - not needed after `foo()`
    void foo();
    void bar(){
      int x = 1;
      foo();
    }

    // Smart compiler knows `foo()` will not return.
    void foo(){
      while(true);
    }
    void bar(){
      int x = rand();
      foo();
      printf("%d\n", x);
    }

    // optimized out
    void bar(){
      int x = 1;
      foo();
      printf("%d\n", x);//  Could complies as `puts("1");`
    }
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
-2

Please read article http://www.geeksforgeeks.org/memory-layout-of-c-program/ to understand program layout.

To answer your question. all the function calls and local variable are saved on stack.

So when you call main, int x, they got pushed on stack and then you will push Foo function on stack along with int y.

Then you again push main and int x, so you will do it infinitely, and eventually you will receive an error saying stack overflow.

Ritesh
  • 1,809
  • 1
  • 14
  • 16
  • 1
    Not going to down vote but calling `main` from the program is undefined behavior. We can have no concrete idea what will happen if `foo` calls `main` – NathanOliver Mar 07 '16 at 20:40
  • 1
    Functions and function calls are not pushed on the stack. Return addresses and base pointers are. – user207421 Mar 07 '16 at 20:44
  • May be I didn't used the right words, but the idea was about the return address and base pointers and I wanted to be simple. And I don't know what happened, When I saw the question, I guess it was main and foo :). But you can always call main function from foo. Its just another function name, but that will cause grief for sure. – Ritesh Mar 07 '16 at 21:04
  • Of course you **can** call `main` from `foo`, but that is simply [undefined behavior](http://stackoverflow.com/questions/2128321/can-main-function-call-itself-in-c). No guarantees hold, if you do. – IInspectable Mar 07 '16 at 21:26