【发布时间】:2021-11-04 07:47:39
【问题描述】:
假设我们有以下代码:
#include <exception>
void funcA() {
funcB();
}
void funcB() {
funcC();
}
void funcC() {
funcD();
}
void funcD() {
throw std::runtime_error("Exception!!"); //3
}
void funcE() {
int * p;
delete p; //4
}
int main (int argc, char **argv) {
try {
funcA(); //1
} catch (std::exception exc) {
std::cerr << exc.what() << endl; //2
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
我想以多线程高效的方式打印堆栈跟踪以及引发异常的行号。
过去几天我一直在检查人们正在采取的解决方案和方法,但不幸的是,在我的情况下没有任何用处。例如,我可以使用 //2 中的 boost 库 boost::stacktrace::stacktrace() 或任何其他库,但这里的问题是我必须捕获异常才能执行此操作,如果您的代码有数百个嵌套函数,这种方法效率不高。您不能只检查所有这些并用try-catch 包装每个并单独处理它们。
所以基本上我需要做的是,如果在//3 处引发异常,我应该能够在 `//2
我知道堆栈展开以及它是如何工作的,但据我了解,每当您的代码到达 catch 块时,这意味着异常堆栈已展开并且您无法获取它。 如果我错了,请纠正我!
有没有办法在展开异常堆栈之前至少添加类似于中间件的东西?还是我必须手动完成?
编辑:
另外,当我可以funcE() 时会发生什么是内存访问异常,但这个异常永远不会被捕获。有没有办法捕获此类异常或至少在崩溃前打印其堆栈跟踪?
注意:
我在 Linux 和 macOS、C++11 和 Silicon Web 框架上运行我的代码。 这是一个很大的系统,所以我正在尝试实现一些可以在整个系统中使用的日志记录机制。
【问题讨论】:
-
与其抛出像
runtime_error这样的通用异常,不如添加您自己的类层次结构,其中包含更多语义上重要的异常,这有助于缩小可能引发每个异常的位置。然后为每个异常添加一些重要的描述,以便每个文本都是唯一的,并且可以用于定位引发异常的确切位置。 -
另一种可能的方式(可以与上面结合)是使用一个特殊的函数甚至预处理宏来抛出异常,这个函数或宏可以添加诸如回溯或源位置,可以是日志,也可以是异常本身的一部分。
-
我添加了
runtime_error作为示例,代码可能会抛出任何类型的异常,我无法将try-catch块添加到系统中的所有函数中,即使我有一个自定义异常类@Someprogrammerdude -
我可以搜索关于宏的任何示例或概念吗? @Someprogrammerdude 提前谢谢老兄:)
-
你不应该在任何地方添加
try catch,只有在某些高处才有意义并且可以实际处理异常。另请注意,某些异常可能无法处理,您应该让它们继续运行以终止程序。还要记住,应该为真正的异常问题保留异常。如果您有一个可以恢复的错误(例如无法打开 可选 文件),那么通常不需要为此抛出异常。
标签: c++11 exception stack-trace stack-unwinding