c++ - 试图在递归函数 : Unhandled exception/Stack overflow 中捕获失败的分配

标签 c++ list exception recursion allocation

这是我要为学校作业解决的问题。我创建了一个包含节点(即包含字符“item”和节点指针“next”的结构)和节点指针头的单个链表类。根据作业的规定,我需要递归地对链表执行多个操作。我已经设法让所有这些工作正常。

但是,作为作业的下一步,我被要求:“编写一个测试程序以确定最长可能的链表是多少。(您将测试堆大小)。您可以这样做很容易,因为附加函数被定义为如果成功则返回 true,否则返回 false。”

在类里面,有人提到我们应该使用类似

的东西
try{ //Allocate a new node
     // Throw an exception if it fails
}
catch(...){
     // Do something with the caught exception
}

对于我来说,我无法让它工作!我收到以下错误:

Assignment.exe 中 0x7765DED4 (ntdll.dll) 处的未处理异常:0xC00000FD:堆栈溢出(参数:0x00000001、0x00352FFC)。

这是我第一次处理异常,所以也许我遗漏了一些东西,但我已经在谷歌和我的教科书集中搜索了几个小时,我正式陷入困境。

这里是有问题的代码:

// RECURSIVELY appends an element to the end of the list
bool LinkedList::append(char newChar){ 
    if (head == nullptr){ // Adds a node to empty list
        head = new Node{ newChar, nullptr };
        return true;
    }
    return appendHelper(newChar, head); // Call the recursive helper function
}

// Helper function for append
bool LinkedList::appendHelper(char newChar, Node* currentNode){     
    if (currentNode->next == nullptr){ // Adds a node to the end of a list

        // HERE'S WHERE THE TROUBLE BEGINS:
        try{
            currentNode->next = new Node{ newChar, nullptr }; // From what I've read, this should throw std::bad_alloc if it fails?
        }
        catch(...){ // The "..." should catch ANY exception, right?
            return false; // Return false, so that I'll know allocation failed
        }
        return true; // Mustn't have encountered an exception; return true.
    }
    return appendHelper(newChar, currentNode->next);
}

我非常有信心,除了异常处理之外,我的代码可以正常工作。 IE。使用以下方法添加节点:

currentNode->next = new Node{ newChar, nullptr };

似乎工作正常。我们在类里面进行的讨论给我的印象是,我应该能够在分配失败时捕获异常,返回 false,然后继续我的程序/实验的其余部分...

知道我哪里出错了,或者我该如何解决这个问题?我开始认为我应该在每次调用 append() 函数时迭代一个计数器并将其打印到屏幕上,然后在它崩溃时记录这个数字......但这并没有看起来很优雅,我也不觉得这是预期的。

最佳答案

你必须区分两种异常:硬件异常软件异常。 C++异常可以认为是软件异常,所以使用C++ try/catch语句只能捕获软件异常。软件异常的一个例子是当程序检测到为某些过程指定了无效参数时。

硬件异常要严重得多,由 CPU 本身抛出。硬件异常的示例有:被零除、试图访问无效内存地址、堆栈溢出 等。其中许多硬件异常由操作系统本身处理(调试器也处理其中一些异常),强烈建议不要在您的程序中捕获这些异常。这样做可能会阻止较低级别的系统正确清理留下的烂摊子。

所以回到你遇到的堆栈溢出问题,当这个硬件异常发生时,堆栈指针已经超出了堆栈边界。换句话说,你的程序出栈了(这是过于简单化了,因为进程中的每个线程都获得了一定数量的栈空间,所以可能只有线程出栈了)。即使你会处理这个异常你想做什么?您的堆栈不足,因此您的选择非常有限(例如,即使定义局部变量或调用函数也可能会导致另一个异常)。

这就是程序不应处理此类异常的原因 - 在应用程序级别,您只是没有足够的智慧来正确恢复,而操作系统能够清理您的应用程序产生的困惑。

也就是说,Windows 允许您捕获此类异常...结构化异常处理 可用于捕获 Windows 上的硬件和软件异常。但是,如果您是聪明的程序员,您可能不会这样做。

Structured Exception Handling

More on hardware exceptions

关于c++ - 试图在递归函数 : Unhandled exception/Stack overflow 中捕获失败的分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32686574/

相关文章:

c++ - 有没有办法教 Android Studio 在将鼠标悬停在变量上时如何显示 C++ 结构?

c++ - 如何在Qt 5.3中使用QCamera设置图像分辨率?

c++ - 在函数中分配但不在外部分配的私有(private)变量

list - 迭代后的Python zip对象 'disappears'?

python - 有没有办法用 less "nesting"写?

android - 如何使用 NewRelic 发送捕获的异常?

java - JPA/Hibernate Exceptions 没有翻译吗?

c# - 集合被修改;枚举操作不能在 ArrayList 中执行

c++ - 为什么我的代码在终端中没有输出任何内容。开始新行没有错误

r - 如何将列表列表从宽变长