提问人:stackoverfIow 提问时间:6/16/2023 更新时间:6/16/2023 访问量:52
C++ 错误处理,无需绕过堆栈展开过程
C++ Error Handling without bypassing stack unwinding process
问:
我希望在由许多源文件和头文件组成的代码中进行干净的错误处理。我更喜欢使用传统的 C 样式状态代码(调用函数,成功时返回 1,然后检查返回值是否为 1),如果状态代码不是 1,那么我想调用一个错误函数,如下所示。这样一来,我就不必在我的程序中到处发送垃圾邮件 try-catch,它允许我描述代码中可能发生的实际错误。我在下面的示例中遇到的问题是我需要清理内存(假设打开了数据库之类的东西),并且必须在程序退出之前关闭它以避免进一步的问题。为了实现这一点,我想利用 RAII,这意味着当堆栈展开过程开始时,应该调用类的析构函数。但是,很明显,在下面的示例中从未调用析构函数,因为 cout 不会发生。我知道这可以通过使用 try-catch 捕获所有错误来避免,否则堆栈倒带是“实现定义的”(哪个实现?这是指我的代码吗?但我真的想避免经常把所有东西都放在 try-catch 中,因为我的可读性会大大受到影响。
这是我的问题:是否可以只调整函数,以便在一切停止之前调用析构函数(我想做正常的堆栈展开)?如果不可能,为什么?这似乎是每个人都应该遇到的简单问题,所以我很惊讶没有发现 sth 会首先调用所有析构函数,而不是 throw。我知道这里有很多关于 RAII 的问题,但通读它们并没有帮助我解决我的问题。throw_error()
safe_throw
感谢您的帮助。这是我的示例代码:
#include <iostream>
using namespace std;
void throw_error(const string& error_description){
throw runtime_error(error_description); // i would like to have a different function that does the same thing except that the stack unwind happens
}
class DatabaseExample{
public:
// constructor
DatabaseExample(){
testarray = new int[32]; // can lead to memory leak if not deleted manually (class is called DatabaseExample because I plan to open a database connection and the leak would be not closing the database connection properly, this is just a simplified example)
}
// destructor, which sadly is never called because exit() or throw avoids the stack unwind which would call the destructor :(
~DatabaseExample(){
cout << "Destructor of the class has been called.. Or has it?" << endl;
delete[] testarray;
}
private:
int* testarray;
};
int main(){
DatabaseExample testobject = DatabaseExample();
int a = 2; // simplified example
if (a != 1){ // openssl library returns 1 on success
throw_error("My custom error that occured because...");
}
return 0; // imagine having 0 chosen as a status value convention from a successful program when from a boolean perspective 0 means FALSE.. Everything worked as expected and the program succeeded in everything it was supposed to do and yet it is supposed to return false
}
答:
你描述的异常的缺点让我觉得你真的不知道如何正确使用它们。在实践中,在使用异常来传达错误的程序中,您只需要很少的 try-catches - 仅当您想要从异常中恢复时。
谁在实现未捕获异常的行为取决于:编译器实现的问题。
您可以通过在主目录中放置一个 try-catch 并简单地记录 + 退出来解决您当前的问题。所有例外情况都将冒泡到此时,届时将发生堆栈展开。如果使用多个线程,则必须在启动的每个线程的入口点中执行此操作。
但是我的 2 美分:如果你这样做,你还不如取消错误代码,首先正确使用异常。现在,通过将错误代码转换为异常来混合这两种方法。
评论
上一个:为什么使用具有唯一锁的延迟锁
评论