在这段代码引发问题之前,调用堆栈可以有多大

How big can call stack be before this code causes trouble?

本文关键字:堆栈 调用 问题 段代码 代码      更新时间:2023-10-16

我优化了链表析构函数,如下所示:

template <class T>
class LinkedList
{
    /* snip */
    T* pData;
    LinkedList* pNext;
};
template <class T>
LinkedList<T>::~LinkedList()
{
    delete pData;
    delete pNext;
}

现在我有点担心它可能会在大名单上引起麻烦。此代码会导致堆栈溢出吗?如果是,在多大的名单上?

堆栈的大小由许多因素决定,例如系统上的操作系统/编译器/配置设置。

我绝对不会使用递归方法来删除列表中的元素,因为你很可能会溢出堆栈-你可以通过创建一个包含X个元素的列表来尝试,如果有效的话,加倍X,直到达到堆栈溢出-我几乎可以保证它发生在几千个元素内(可能是10-100k,但肯定不会超过这个)。

删除二叉树之类的递归函数更容易被接受,因为(假设合理的平衡)递归级别的数量是log2(n),而不是n,所以在堆栈溢出之前可以有大量的元素。

我选修了你的课程,并将其扩展为"有效"(这可能与你使用它的方式完全不同,但它可以解释问题):

#include <iostream>
using namespace std;
template <class T>
class LinkedList
{
public:
    LinkedList() : pNext(0), pData(0) {};
    LinkedList(T e) : pNext(0) { pData = new T(e); }
    LinkedList(LinkedList* l, T e) : LinkedList(e) { pNext = l;}
    LinkedList *AppendFirst(LinkedList *l) { l->pNext = this ; return l; }
    LinkedList *Next() { return pNext; }
    T Data() { return *pData; }
    ~LinkedList();
private:
    T* pData;
    LinkedList* pNext;
};
#if 0
template <class T>
LinkedList<T>::~LinkedList()
{
    delete pData;
    delete pNext;
};
#else
template <class T>
LinkedList<T>::~LinkedList()
{
    LinkedList<T>* p;
    LinkedList<T>* q;
    p = pNext;
    while(p)
    {
        q = p->pNext;   // Save next link. 
        p->pNext = NULL;   // Break the link. 
        delete p->pData;
        p->pData = NULL;
        delete p;
        p = q;
    }
    delete pData;
};
#endif

typedef LinkedList<int> IntList;
int main()
{
    for(int x = 0; x < 30; x++)
    {
        cout << "Trying " << (1 << x) << " elements" << endl;
        IntList *head = new IntList(-1);
        for(int i = 0; i < (1 << x); i++)
        {
            head = head->AppendFirst(new IntList(i));
        }
        cout << "Now destroying " << (1 << x) << " elements" << endl;
        delete head;
    }
}

如果我将#if 0更改为#if 1(或其他具有这种效果的东西),它适用于128K元素,并在256K时崩溃。如果我在#else中使用迭代方法,当它达到268435456(256M个条目)时,我不得不停止它,因为我的机器没有足够的内存,并且开始进行糟糕的交换(我只有16GB的RAM,这不仅仅是这样)。