我在Mac上,我正在使用clang ++(别名为g ++)。
我正在尝试用C ++打印类似Python的堆栈跟踪。
我愿意使用框架和/或其他编译器,但我需要它在mac或ubuntu上运行。
我已经检查了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();
答案 0 :(得分:0)
这是我用于创建带有回溯(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
构建完整信息。