如果我有以下代码:
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;
答案 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;
}
调用这些函数之一会导致堆栈帧重复分配到堆栈,直到超出操作系统指定的限制。
答案 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,所以你将无限地执行它,最终你会收到一个错误,说堆栈溢出。