gpt4 book ai didi

C++ 漂亮的堆栈跟踪

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:51:45 25 4
gpt4 key购买 nike

我在 Mac 上使用 clang++(别名为 g++)。

我正在尝试在 C++ 中打印类似 Python 的堆栈跟踪。

我愿意使用框架和/或其他编译器,但我需要它在 mac 或 ubuntu 上运行。

我已经 checkout backtrace ,但它似乎有点原始——我宁愿不必计算字节数来找出堆栈跟踪中每一行所指的源代码中的位置。

此外,如果它是相关的,我真的不需要任何优化,所以如果有帮助,我愿意关闭优化。此外,如果我可以使用 C++11 功能,我会更喜欢它(如果你建议我使用不同的编译器)。


作为我希望能够做的事情的一个简单示例,理想情况下我会运行

g++ MySource.cpp -o MyProgram <magic options>

MySource.cpp 可能看起来像

#include "MyHeader.hpp"

int main() {
test();
}

MyHeader.hpp 可能看起来像

#include <magic_print_stacktrace_library>

void test() {
magic_print_stacktrace_function();
}

如果我要运行 ./MyProgram,我希望看到类似的东西

File "MyHeader.hpp", line 4, in test
magic_print_stack_tracefunction();
File "MySource.cpp", line 4, in main
test();

最佳答案

下面是我用 backtrace(3) 创建回溯的一些代码:

#include <errno.h>
#include <execinfo.h>
#include <unistd.h>

/*
* call external program addr2line WITHOUT using malloc or stdio or anything
* else that might be problematic if there's memory corruption or exhaustion
*/
const char *addr2line(void *addr, const char *text)
{
int pfd[2], len;
pid_t child;
static char buffer[1024], *p;
const char *argv[5] = { "addr2line", buffer, "-e", program_name, 0 };
uintptr_t a = (uintptr_t)addr;
if (pipe(pfd) < 0) return 0;
p = buffer + sizeof(buffer) - 1;
*p = 0;
while (p > buffer) {
*--p = "0123456789abcdef"[a&0xf];
if (!(a >>= 4)) break; }
argv[1] = p;
if (text && (p = (char *)strchr(text, '('))) {
strncpy(buffer, text, p-text);
buffer[p-text] = 0;
argv[3] = buffer; }
while ((child = fork()) == -1 && errno == EAGAIN);
if (child == -1) return 0;
if (child == 0) {
dup2(pfd[1], 1);
dup2(pfd[1], 2);
close(pfd[0]);
close(pfd[1]);
execvp(argv[0], (char*const*)argv);
_exit(-1); }
close(pfd[1]);
p = buffer;
while (p < buffer + sizeof(buffer) - 1 &&
(len = read(pfd[0], p, buffer+sizeof(buffer)-p-1)) > 0 &&
(p += len) && !memchr(p-len, '\n', len));
close(pfd[0]);
waitpid(child, &len, WNOHANG);
*p = 0;
if ((p = strchr(buffer, '\n'))) *p = 0;
if (buffer[0] == 0 || buffer[0] == '?')
return 0;
return buffer;
}


void stacktrace() {
static void *buffer[64];
int size = backtrace(buffer, 64);
char **strings = backtrace_symbols(buffer, size);
for (int i = 1; i < size; i++) {
if (strings)
std::endl << " " << strings[i] << std::endl;
if (const char *line = addr2line(buffer[i], strings ? strings[i] : 0))
std::cerr << " " << line << std::endl; }
if (size < 1)
std::cerr << "backtrace failed" << std::endl;
}

请注意,它需要知道可执行文件的路径(上面的 program_name),并且需要使用 -g 构建它以获得完整信息。

关于C++ 漂亮的堆栈跟踪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27339138/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com