当函数调用另一个函数时,函数使用的内存会发生什么变化?

时间:2016-03-07 20:28:17

标签: c++ c memory

如果我有以下代码:

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

void foo(){
    while(true);
}

调用int x时,bar()中使用的内存foo()会发生什么?它被释放了吗?

我知道如果函数返回,则释放内存,但在这种情况下函数根本不会返回。

如果我使用此代码,其中bar调用foo,而bar调用void bar(){ int x = 1; foo(); } void foo(){ int y = 1; bar(); } 等等,程序最终会耗尽内存,或者旧的功能的实例被新的实例替换?

my @sorted = sort {$a <=> $b} @permutednumbers;

6 个答案:

答案 0 :(得分:5)

在这种情况下,x在堆栈上分配。当你调用函数foo()时,存储在堆栈中的所有变量都保持分配 - 新函数使用新的堆栈'frame'。这是必需的,因为如果函数foo()曾经返回,那么它需要能够访问旧堆栈帧上的变量'x'。如果新函数(foo)调用另一个函数,那么两者仍然会消耗它们的堆栈内存。如果foo以递归方式调用foo,则每个递归调用都会有一个新的'foo'堆栈帧(以及为变量y分配的堆栈空间)。如果有太多的函数调用占用过多的堆栈空间(递归或不递送),最终会耗尽堆栈空间,程序将失败。

答案 1 :(得分:2)

  

调用int x时,bar()中使用的内存foo()会发生什么?它被释放了吗?

我知道如果函数返回,则释放内存,但在这种情况下函数根本不会返回。

不,它没有被释放。当bar返回时,x变量被释放,这在你的情况下永远不会发生。

  

如果我使用此代码,其中bar调用foo,而bar调用Random random = new Random();等等,程序最终会耗尽内存,或者旧的功能的实例被新的实例替换?

你最终会得到堆栈溢出,因为你永远不会释放局部变量(因为你永远不会返回),并且每个线程只有有限的堆栈空间可用。在使用MSVC的Windows中,它是1MB。

答案 2 :(得分:2)

您描述的结束条件称为堆栈溢出,是的,程序最终会在其堆栈段中耗尽内存。调用每个函数时,在堆栈上分配一个空间,用于保存需要运行的数据,称为堆栈帧

__global__ void kernel(int *gpu_mem, int *gpu_mem_offset)
{
    gpu_mem[(*gpu_mem_offset)++] = some_value;
}

调用这些函数之一会导致堆栈帧重复分配到堆栈,直到超出操作系统指定的限制。

请参阅https://en.wikipedia.org/wiki/Call_stack

答案 3 :(得分:1)

内存保留在堆栈上,堆栈指针移动,为main()中的局部变量腾出空间。实际上,整个堆栈帧都被保留了下来。如果再次调用bar(),则会在堆栈上锁定更多内存。在某些时候,您将有一个堆栈溢出,不要与http://www.stackoverflow/混淆。

答案 4 :(得分:1)

  

函数(bar())在调用另一个函数(foo())时使用的内存会发生什么变化?

如果bar()可能返回并且在通话后使用内存,则内存将保持活动状态。

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

记忆可能存在或不存在的情况

    // 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");`
    }

答案 5 :(得分:-3)

请阅读文章http://www.geeksforgeeks.org/memory-layout-of-c-program/以了解计划布局。

回答你的问题。所有函数调用和局部变量都保存在堆栈中。

因此,当你调用main,int x时,它们被推入堆栈,然后你将在堆栈上推送Foo函数和int y。

然后你再次推送main和int x,所以你将无限地执行它,最终你会收到一个错误,说堆栈溢出。