首先,因为不能保证C标准中的任何调用堆栈。(可以想象某些C编译器会进行整个程序分析,并在无用的情况下避免栈,例如,如果不能进行递归;我不知道这种C编译器)。有关奇怪的C实现,请参见此C FAQ问题。
然后,因为编译器有时可能会做一些优化,例如内联一些调用(甚至是对未标记的函数进行内联inline,尤其是在要求传递给to的链接时优化时),或者有时会发出尾部调用(而GCC可以同时执行)。您可以禁用优化,但是会损失很多性能。一个优化的编译器将只在寄存器中放置一些变量,并为某些变量重用一些堆栈槽。-fltogcc
最后,在某些体系结构(例如32位x86)上,可能会使用某些代码(尤其是某些库代码,例如libc内)进行编译,-fomit-frame-pointer然后如果没有它就无法获取帧信息。
您可以在GCC中使用libbacktraceby by Ian Taylor;您还可以使用GNU glibc的backtrace(3)函数;您甚至可以使用与GCC一起编译时可用的返回地址内置函数。但是所有这些工具可能无法在优化的代码上运行。
实际上,如果您确实需要一些回溯,则可以自己实现(我在我的过时的MELT系统中做到了,通过将局部变量包装在局部区域中来生成C ++代码struct),或者避免进行过多的优化(例如gcc -g -O1仅通过编译)。
请注意,backtrace是不是一个系统调用(中列出的系统调用(2) ,但一)glibc特异性库函数。
还请仔细阅读signal(7)和sigreturn(2)。可以从信号处理程序可靠地(直接或间接)调用的功能(异步信号安全)很少,并且backtrace(或printf)功能不在其中。在实践中,便携式信号处理程序通常应该只设置一些volatile sigatomic_t标志,然后在其他位置进行测试-或调用siglongjmp(3)。
| 归档时间: |
|
| 查看次数: |
955 次 |
| 最近记录: |