backtrace()栈回溯偏移1行:main函数栈帧定位异常
栈回溯中main函数栈帧定位偏移的原因
你遇到的问题核心是函数调用的返回地址机制导致的:当CPU执行call old_backtrace指令时,会自动把下一条指令的地址压入栈中,作为函数返回后要执行的位置。backtrace获取到的栈帧地址正是这个返回地址,而非调用指令call本身的地址。
具体场景拆解
你的main函数里,调用old_backtrace()的行之后是char* foo;的定义(对应代码第25行)。编译后,call old_backtrace的下一条指令就对应这一行的内存位置,所以backtrace给出的main+0x18实际是这个返回地址。用addr2line解析时,这个地址会映射到它所在的代码行(第25行),而非调用old_backtrace()的行。
而你把地址减1后,就指向了call old_backtrace指令所在的内存位置,自然就能正确定位到调用点的代码行。
补充说明
- 这个行为是x86_64架构和System V ABI的固有机制,和编译优化级别(你用的-O0)无关。
old_backtrace()的地址定位准确,是因为backtrace捕获的是进入该函数后的栈帧起点,对应函数内执行的第一条指令位置,和函数调用的返回地址机制不冲突。
你的代码示例
#include <execinfo.h> #include <stdlib.h> #include <stdio.h> void old_backtrace() { int m_maxNumFrames = 30; void** m_frames = (void**)malloc(m_maxNumFrames * sizeof(void*)); int m_numFrames = backtrace(m_frames, m_maxNumFrames); char** strs = backtrace_symbols(m_frames, m_numFrames); printf("Call stack:\n"); for (int i = 0; i < m_numFrames; ++i) { printf("%s\n", strs[i]); } } int main(int argn, char** argc) { old_backtrace(); char* foo; }
编译命令
gcc -g3 -rdynamic -O0 test.cpp -o output
栈回溯输出
./output(_Z13old_backtracev+0x39) [0x555fc6b201e2] ./output(main+0x18) [0x555fc6b20259] /lib/x86_64-linux-gnu/libc.so.6(+0x29d90) [0x7f27645f9d90] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0x80) [0x7f27645f9e40] ./output(_start+0x25) [0x555fc6b200e5]
内容的提问来源于stack exchange,提问作者Steve
相关产品推荐
相关产品推荐

