【发布时间】:2014-04-21 05:24:59
【问题描述】:
调用递归函数时如何分配内存? 一个函数有它自己分配的内存。当它被调用时,参数(不是引用传递的)和变量获得内存。那么当函数在函数体内再次被调用时,内存是如何分配给第二次调用的变量和参数的呢?
【问题讨论】:
标签: c++ c memory memory-management recursion
调用递归函数时如何分配内存? 一个函数有它自己分配的内存。当它被调用时,参数(不是引用传递的)和变量获得内存。那么当函数在函数体内再次被调用时,内存是如何分配给第二次调用的变量和参数的呢?
【问题讨论】:
标签: c++ c memory memory-management recursion
递归函数与任何其他函数没有什么不同——自动局部变量被分配为一个单独的块,通过将堆栈指针推进足够远来解释它们的大小总和(加上对齐所需的任何填充)。
每个递归调用都以这种方式推送一个新的堆栈帧,然后在返回时将其弹出。如果递归未能达到基本情况,堆栈将迅速耗尽,从而导致同名的堆栈溢出崩溃。
【讨论】:
递归调用函数就像任何其他函数一样。因此,内存的分配方式与调用任何常规函数的方式相同。
【讨论】:
它与调用任何其他函数相同。变量(不是引用传递的)在堆栈上分配。当函数开始返回时(即达到基本情况),堆栈会按照每个嵌套递归调用被推入堆栈的顺序弹出。
这个 youtube 视频很好地解释了递归函数的调用堆栈:https://www.youtube.com/watch?v=k0bb7UYy0pY
【讨论】:
PUSH 和 POP 操作。那只能在堆栈上。顺便说一句,“自动管理的内存”是什么意思?
当一个函数(调用func1)调用另一个函数(调用它func2)时,执行func2所需的数据被压入堆栈。这对于递归函数不会改变(当func2 与func1 相同时)。
如果递归函数被递归调用10 次,将有10 堆栈帧,每个对应于该函数的一次调用。
【讨论】:
当一个函数被调用时,必要的参数被压入堆栈。当一个函数完成它的任务时,参数被弹出并且程序计数器被恢复。
递归函数也不例外。
【讨论】:
自动变量的内存分配在stack。当您调用另一个函数(递归 self 或其他函数)时,堆栈帧到目前为止仍处于其状态,我们在堆栈上分配更多内存(假设是这样)来存放这个新函数的局部变量。当函数结束时,新的堆栈帧被丢弃,我们恢复到之前的(calee)堆栈帧。
您可以使用您选择的任何调试器来更好地理解事物。有不明白的请追问。
【讨论】:
递归使用堆栈内存来执行
看下面的例子
void rev(Node* head){
if(head==NULL) return;
head=head->next;
rev(head);
cout<<head->data<<endl;}
让我们看看堆栈段中的递归。
设NODE1 -> NODE2->NULL 其中 NODE1 和 NODE2 是结构对象。
你的函数在做什么:
Call to rev(NODE1)
Check if it is NULL
Point to next NODE i.e. NODE2
Call to rev(NODE2)
Check if It is NULL
Point to next NODE i.e. NULL
Call to rev(NULL)
Check if It is NULL
Pointer will be returned With head = NULL
希望对您有所帮助。
【讨论】:
您编写的函数(代码行)存储在文本段中,当它被调用时,它会在堆栈内存中分配一个帧,变量(静态除外)的内存也会在给定帧的堆栈中分配。
递归函数没有什么不同,它也是被调用 n 次的普通函数。所以它的内存(帧)也在堆栈上分配了 n 次。
【讨论】:
当一个函数被调用时,它的参数与其他函数状态一起保存在堆栈中。
函数调用过程中构造的栈帧包含以下内容:
【讨论】:
函数参数和局部变量在栈上分配。它们形成了所谓的stack frame。当一个函数被递归调用时,每个函数的递归调用都会分配一个栈帧。
例如if void f() 被递归调用了 3 次。
// Assume stack grows upwards
stack frame #3 <== the most recent call
stack frame #2
stack frame #1
【讨论】:
使用后需要释放内存。
这里有一个示例程序来说明这一点。
http://forums.devx.com/showthread.php?145311-Free-memory-or-garbage-in-recursion-program
【讨论】: