backtrace实操总结

本文介绍了-g和-rdynamic在编译和链接过程中的作用,重点讨论了如何使用backtrace函数,强调了ELF二进制格式和-rdynamic选项的重要性。还提到了在优化编译时的注意事项,如避免某些优化选项干扰堆栈信息,以及如何处理各种信号以获得正确的backtrace。此外,还分享了如何通过环境变量控制backtrace输出到文件中,并给出了不同编译选项对程序大小的影响。

-g与-rdynamic的异同:

-g 是一个编译选项,在编译的过程中起作用,把更多调试信息(也就包括符号信息)存放到最终的可执行文件内。
-rdynamic 是一个连接选项,将指示连接器把所有符号都添加到动态符号表(即.dynsym表)里,以便dlopen()或backtrace()这样的函数使用。

要使用 backtrace 函数, 有两点要求:

1)程序使用的是 ELF 二进制格式.
2)程序连接时使用了 -rdynamic 选项.
-rdynamic可用来通知链接器将所有符号添加到动态符号表中, 这些信息比 -g 选项的信息要少得多.

注意事项:

① 某些编译器的优化选项对获取正确的调用堆栈有干扰, 另外内联函数没有堆栈框架;
删除框架指针也会导致无法正确解析堆栈内容;

② backtrace使用,最好被监控的信号:
https://www.cnblogs.com/frisk/p/11602973.html
SET_SIG(SIGILL) 4 //非法指令
SET_SIG(SIGBUS) 7 //总线错误
SET_SIG(SIGFPE) 8 //浮点异常,即除0异常
SET_SIG(SIGABRT) 6 //来自abort函数的终止信号
SET_SIG(SIGSEGV) 11 //无效的存储器引用(段错误)
SET_SIG(SIGPIPE ) 13 //向一个没有读用户的管道做写操作
SET_SIG(SIGTERM) 15 //软件终止信号
SET_SIG(SIGSTKFLT ) 16 //协处理器上的栈故障
SET_SIG(SIGXFSZ) 25 //文件大小超出限制
SET_SIG(SIGTRAP ) 5 //跟踪陷阱
去除SIGINT,SIGKILL时对backtrace打印。

③ 通过环境变量来控制 backtrace 输出到文件中:
getenv()用来取得参数envvar环境变量的内容
ftell获取文件的大小
ftruncate(fd, 0); //清空文件
lseek(fd, 0, SEEK_SET);

试验总结:

(“ENV{CXXFLAGS} -O0 -g -ggdb -Werror -Wall -Wno-unknown-pragmas”) //编译出200M
(“ENV{CXXFLAGS} -O0 -rdynamic -Werror -Wall -Wno-unknown-pragmas”) //编译出38M,用于RELEASE版优化不好
(“ENV{CXXFLAGS} -O3 -rdynamic -Werror -Wall -Wno-unknown-pragmas”) //*编译出33M,可用于RELEASE和backtrace
(“ENV{CXXFLAGS} -O3 -Werror -Wall -Wno-unknown-pragmas”) //编译出33M,用于RELEASE

参考网:

Linux进程崩溃异常退出的调试方法
gcc选项-g与-rdynamic的异同:https://www.cnblogs.com/LiuYanYGZ/p/5550544.html

SIGABRT:
来自于abort函数: 立即终止当前进程,产生异常程序终止.这种方式可能会或可能不会以刷新与关闭打开的文件或删除临时文件,这与你的设计有关. 程序自己发现错误并调用abort时产生. exit: 附加了关闭打开文件与返回状态码给执行环境.

SIGILL:
illegal instruction是POSIX标准中提供的一类错误。某个进程中的某一句不能被CPU识别成正确的指令。在进程试图执行一些形式错误、未知或者特权指令时操作系统会使用SIGILL信号终止程序。对于堆栈溢出时也有可能产生这个信号.
https://blog.csdn.net/SoaringLee_fighting/article/details/89319340

SIGBUS:
非法地址, 包括内存地址对齐(alignment)出错.它的缺省行为是终止当前进程并产生core dump。
https://www.cnblogs.com/wzjhoutai/p/6747625.html

SIGFPE:
浮点异常,即除0异常

SIGPIPE:
默认好像是终止进程,向一个没有读进程的管道写数据. TCP通信产生SIGPIPE信号原因与解决方法:https://blog.csdn.net/u010821666/article/details/81841755

SIGSTKFLT:
该信号仅仅在Linux中有定义,出现在早期的Linux系统中,其原意是用于数字协处理器的堆栈错误。该信号在内核中并不会被产生,但是为了兼容性被保留下来了。

SIGXFSZ:
当某个进程写文件,单个文件大小超出限制,这时操作系统会向它发送SIGXFSZ。该信号的默认动作是:终止进程+生成coredump文件。

SIGTRAP:
由断点指令或其它trap指令产生. 由debugger使用.
SIGTRAP代表陷阱信号。它并不是一个真正的崩溃信号。它会在处理器执行trap指令发送。LLDB调试器通常会处理此信号,并在指定的断点处停止运行。如果你收到了原因不明的SIGTRAP,先清除上次的输出,然后重新进行构建通常能解决这个问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值