【发布时间】:2021-06-18 14:15:03
【问题描述】:
在perf record --call-graph dwarf 生成并由perf script 打印的回溯中,我一直在为大约 5% 的调用堆栈获取错误的地址,即展开失败。一个例子是
my_bin 770395 705462.825887: 3560360 cycles:
7f0398b9b7e2 __vsnprintf_internal+0x12 (/usr/lib/x86_64-linux-gnu/libc-2.32.so)
7ffcdb6fbfdf [unknown] ([stack])
my_bin 770395 705462.827040: 3447195 cycles:
7f0398ba1624 __GI__IO_default_xsputn+0x104 (inlined)
7ffcdb6fb7af [unknown] ([stack])
它是由这段代码产生的(用g++ -O3 -g -fno-omit-frame-pointer my_bin.cpp -o my_bin编译):
#include <cstdio>
#include <iostream>
int __attribute__ ((noinline)) libc_string(int x) {
char buf[64] = {0};
// Some nonsense workload using libc
int res = 0;
for (int i = 0; i < x; ++i) {
res += snprintf(buf, 64, "%d %d %d Can I bring my friends to tea?", (i%10), (i%3)*10, i+2);
res = res % 128;
}
return res;
}
int main() {
int result = libc_string(20000000);
std::cout << result << "\n";
}
我很确定我的程序在堆栈中不应该有可执行代码,所以这些地址似乎是错误的。这不仅是一个程序,而且我分析过的大多数程序都有大约 5% 的错误调用堆栈。这些调用栈大多只有两个栈帧,最里面的栈帧有时在 Eigen 之类的库中(尽管它们通常有正确的调用栈),有时在 C++ STL 或 libc 中。我在unknown、[stack]、[heap]、anon、//anon、libstdc++.so.6.0.28 或<my_bin> 中看到了结束。
我在 Ubuntu 18.04、20.04 和 20.10 上看到过这个。
这只发生在 DWARF 展开时。如何解决这个问题?
【问题讨论】:
-
您是否尝试过在其中一个函数中使用 gdb 并查看回溯的样子?
-
@JorgeBellon 是的,它看起来总是正确的。
标签: c++ callstack perf backtrace dwarf