【问题标题】:Recursive Stack in CC中的递归堆栈
【发布时间】:2015-09-12 23:25:14
【问题描述】:

在递归过程中,堆栈被创建,该堆栈包含什么,它包含值还是存储操作数的地址

void recursiveReverse(struct node** head_ref)
{
   struct node* first;
   struct node* rest;

   /* empty list */
   if (*head_ref == NULL)
      return;   

   /* suppose first = {1, 2, 3}, rest = {2, 3} */
   first = *head_ref;  
   rest  = first->next;

   /* List has only one node */
   if (rest == NULL)
      return;   

   /* reverse the rest list and put the first element at the end */
   recursiveReverse(&rest);
   first->next->next  = first;  

   /* tricky step -- see the diagram */
   first->next  = NULL;          

   /* fix the head pointer */
   *head_ref = rest;                 
}

在上面的代码中,休息指针保持最后一个节点的地址,而第一个指针不断变化,即它从堆栈中取值而休息指针没有。 所以首先我想了解递归堆栈,它的结构,它包含的内容,它是如何工作的,以及对上述代码的解释表示赞赏

【问题讨论】:

  • 有一件重要的事情要知道,每当recursiveReverse() 方法被调用(递归地或从任何其他调用者)时,返回地址都会被压入堆栈。
  • 这是C,所以参数的值和返回地址、返回值等都在栈上。看看网上的“栈帧”。

标签: c recursion linked-list stack


【解决方案1】:

我想知道递归堆栈,它的结构,它包含什么,它是如何工作的

递归函数与任何其他函数完全相同。所以对于递归函数的瞬时调用,它将像普通函数一样维护堆栈。每次函数声明一个新变量时,它都会被推送到堆栈中。然后每次函数退出时,该函数压入堆栈的所有变量都被释放(也就是说,它们被删除)。释放堆栈变量后,该内存区域可用于其他堆栈变量。

所以当一个递归函数被调用时,它的所有变量都被压入到堆栈上,当它返回时,堆栈变量被释放。请注意,自动局部变量被分配为单个块和堆栈指针,其先进程度足以说明它们的大小之和。

长话短说,递归函数的每次调用都会占用堆栈中的一块内存。看下面的 C 中无限递归的例子。

int foo() 
{
     int someVariable;
     return foo();
}

函数foo在被调用的时候会继续调用自己,每次都会在栈上分配一块额外的空间,直到栈溢出导致段错误。

有关更多信息,如果我们将foo() 声明如下:

int foo() 
{
    double x[1024];
    return foo();
} 

然后每次递归调用,都会在堆栈中为x分配一个额外的内存1024 * sizeof(double)。但是使用malloc() 将分配 heap 内存而不是 stack

最后,每次递归函数被调用,包括返回值,返回地址也被压入堆栈。

如您所见,每次递归调用都会推送一个新的堆栈帧,然后如果递归未能达到基本情况,堆栈将很快耗尽并导致堆栈溢出。

参考:Stack based memory allocationStack overflowMemory Stack vs Heap

【讨论】:

    猜你喜欢
    • 2013-08-27
    • 2017-01-20
    • 2021-01-21
    • 2013-06-16
    • 2020-09-23
    • 1970-01-01
    • 1970-01-01
    • 2016-11-11
    • 2014-04-12
    相关资源
    最近更新 更多