这个 dumpTrace
函数是一个信号处理程序,用于在接收到特定信号(如崩溃或异常信号)时生成堆栈跟踪,并记录错误信息。下面逐步分析这个函数的每个部分:
参数说明
int sigNum
: 接收到的信号编号。例如,SIGSEGV
、SIGABRT
等。siginfo_t* info
: 指向有关信号的附加信息的结构体,其中包含导致信号产生的信息,例如故障地址等。void* ptr
: 额外的数据,通常不需要使用。
函数功能
日志输出基本信息:
logStream_ << " error number = " << sigNum << "(" << std::string(strsignal(sigNum)) << ")" << std::endl;
- 使用
logStream_
输出发生的错误类型和对应的描述。通过strsignal(sigNum)
获取信号的字符串描述。
- 使用
检查
info
是否为 nullptr:if (info == nullptr) { return; }
- 如果传入的
info
指针为空,直接返回,不进行后续操作。
- 如果传入的
记录故障地址:
logStream_ << "Fault adress: " << std::hex << info->si_addr << std::endl;
- 输出导致故障的内存地址,这有助于调试定位问题。
获取堆栈跟踪信息:
void *buffer[MAX_BT_SIZE] = {0}; size_t nptrs; char **strings = nullptr; nptrs = backtrace(buffer, MAX_BT_SIZE); strings = backtrace_symbols(buffer, nptrs);
- 定义一个缓冲区来存储调用堆栈的信息,然后调用
backtrace()
函数获取当前调用栈中的函数指针数量和相关信息,并将其转换为人类可读格式,通过backtrace_symbols()
。
- 定义一个缓冲区来存储调用堆栈的信息,然后调用
检查
backtrace_symbols()
的结果:if (strings == nullptr) { std::cout << "backtrace_symbols failed" << std::endl; return; }
解析并记录每个堆栈帧的信息:
for (size_t i = 2; i < nptrs; ++i) { ... char* tmp = __cxa_demangle(syb.c_str(), nullptr, 0, &status); if (status == 0 && tmp) { name = std::string(tmp) + " [" + name.substr(0, SymbolStart - sizeof(char)) + "]"; } }
- 遍历堆栈帧,从第3个帧开始(前两个帧可能是系统内部调用)。
- 提取函数名称并尝试对其进行“解魔法”(demangling),以便将 C++ 的名字修饰转换为可读形式。如果成功,将其添加到输出中。
清理资源并打印日志内容: “`cpp free(strings); strings = nullptr;
std::cout << logStream_.str() << std::endl;
8. **恢复旧的信号处理程序并重新抛出信号**:
```cpp
sigaction(sigNum, &oldacts_[sigNum], nullptr);
raise(sigNum);
- 恢复该信号之前注册的处理程序。这一步确保在崩溃情况下能够生成 core dump 文件。
- 使用
raise(sigNum)
再次发送相同的信号,以保持原有行为,如触发核心转储(core dump)。
总结
该函数用于捕获运行时错误并记录详细的调试信息,包括故障类型、故障地址及当前执行堆栈。通过使用这段代码,可以帮助开发者更快速地识别和定位造成程序崩溃的问题。
内容由零声教学AI助手提供,问题来源于学员提问