Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/163.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如果函数引发的异常可能未破坏,如何销毁局部变量?_C++_Exception_Uncaught Exception - Fatal编程技术网

C++ 如果函数引发的异常可能未破坏,如何销毁局部变量?

C++ 如果函数引发的异常可能未破坏,如何销毁局部变量?,c++,exception,uncaught-exception,C++,Exception,Uncaught Exception,当函数在异常未捕获时抛出时,堆栈展开不太可能触发,因此不会调用局部变量的析构函数。例如,以下代码仅在g++7.1.0下输出“已创建”(以及错误消息): #include <iostream> using namespace std; struct A { A() { cerr << "created\n"; } ~A() { cerr << "destroyed\n"; } }; void f() { A a; throw

当函数在异常未捕获时抛出时,堆栈展开不太可能触发,因此不会调用局部变量的析构函数。例如,以下代码仅在g++7.1.0下输出“已创建”(以及错误消息):

#include <iostream>
using namespace std;

struct A {
    A() { cerr << "created\n"; }
    ~A() { cerr << "destroyed\n"; }
};

void f() {
    A a;
    throw 0;
}

int main() {
    f();
}
这样,总是调用
a
的析构函数。然而,我觉得这并不令人满意,因为必须编写一个空catch子句,而且这并不简单

那么以下哪项应该被认为是正确的,或者是否有更好的实践(尤其是在库中实现函数时)

  • 用上面提到的try-catch块包装每个可能抛出的函数
  • 假设此函数的调用方总是捕获异常
  • 因为未捕获异常会导致崩溃,所以我不必破坏局部变量
    main
    函数中放置一个顶级try-catch(…),该函数输出错误消息并退出。这将确保始终进行退绕

    但问题是你为什么要这样。如果您处于任何真实的非嵌入式环境中,操作系统将清理您进程中的所有资源。没有可能。由于还有其他不涉及异常的方法使进程崩溃,所以在这种情况下,您不能依赖析构函数进行清理

    如果您在嵌入式环境中,情况与此类似。您可能没有要清理的操作系统,但崩溃通常会导致设备重置,这具有相同的效果。同样,您不能依赖析构函数,因为还有其他崩溃方法。

    主函数中放置一个顶级try-catch(…),该函数输出错误消息并退出。这将确保始终进行退绕

    但问题是你为什么要这样。如果您处于任何真实的非嵌入式环境中,操作系统将清理您进程中的所有资源。没有可能。由于还有其他不涉及异常的方法使进程崩溃,所以在这种情况下,您不能依赖析构函数进行清理



    如果您在嵌入式环境中,情况与此类似。您可能没有要清理的操作系统,但崩溃通常会导致设备重置,这具有相同的效果。同样,您不能依赖析构函数,因为还有其他崩溃方法。

    您不需要明确地销毁任何东西。局部变量将消失,就像作用域被保留一样。3.是的。这是一道试题吗?重新开始。链接的问题是关于发生平仓的情况,这是关于不发生平仓的情况,因为异常是未捕获的。@SebastianRedl-Hmm。被骗者的答案有一个标准引用,也涵盖了这一点。真是浪费。@TRCYX如前3所述。这是正确的。你到底在担心什么?你不需要明确地破坏任何东西。局部变量将消失,就像作用域被保留一样。3.是的。这是一道试题吗?重新开始。链接的问题是关于发生平仓的情况,这是关于不发生平仓的情况,因为异常是未捕获的。@SebastianRedl-Hmm。被骗者的答案有一个标准引用,也涵盖了这一点。真是浪费。@TRCYX如前3所述。这是正确的。你到底在担心什么?在嵌入式系统中,一些外围硬件可能会处于不良状态,可能需要完全的上电重置。但正如我所说,你不能依赖于析构函数。好吧,这是一个好主意,可以说服我不要过度思考这个问题-D@axalis没错,但这是另一个“是的,但如果你犯错怎么办?”问题的例子。无论如何,你必须为废弃的信号量想出一个解决方案。是的,这是我最近发现的一个bug(调试起来非常困难)。有些情况下,服务的共享内存锁在某种程度上是“保持”的,尽管没有活动客户端可以保持该锁。最后我发现,如果客户机在错误的时间点被Ctrl+C终止,锁仍然被锁定(尚未解决,捕获异常在这种情况下没有帮助,将需要实现一个信号处理程序或类似的东西),某些外围硬件可能处于不良状态,可能需要完全上电复位。但正如我所说,你不能依赖于析构函数。好吧,这是一个好主意,可以说服我不要过度思考这个问题-D@axalis没错,但这是另一个“是的,但如果你犯错怎么办?”问题的例子。无论如何,你必须为废弃的信号量想出一个解决方案。是的,这是我最近发现的一个bug(调试起来非常困难)。有些情况下,服务的共享内存锁在某种程度上是“保持”的,尽管没有活动客户端可以保持该锁。最后我发现,如果客户机在错误的时间点被Ctrl+C终止,锁仍然是锁定的(尚未解决,捕获异常在这种情况下没有帮助,将需要实现一个信号处理程序或类似的东西)。
    void f() try {
        A a;
        throw 0;
    } catch (...) {
        throw;
    }