在linux 编译过程中由于c语言的复杂行导致我们不可能一次写好大工程的代码,经常会出现core dump (有时时内存泄漏或者越界等) 我们怎样快速的排除这些错误呢。
gdb 是个不错的工具他可以很快的调试这类错误。 他分两种调试方法 1. 本地调式,2. 远程调试。 今天我们指讲本地调试,远程调试需要安装搭建gdb server 比较麻烦。
1. gdb 本地调试:
a) 编译app 的及准备工作:
>>设置程序运行终端的core dump 文件大小
ulimit -c unlimited or ulimit -c size
>> 设置code dump 文件名和路径
echo /tmp/core-%e.%p.%h.%t >/proc/sys/kernel/core_pattern
>> app 编译
在编译时需要加入-g 参数不然 经过优化后 gdb 调节出来的 只有地址信息没有 符号(具体行号),不要strip 也不要加入 -s 信息
b) 本地gdb 调试
>> 启动
在编译app 的环境下启动gdb(gdb appname core_dump_file)
也可以在(gdb appnamme) 后用file 命令 导入core_dump 文件。
有时需要加入app 调用的lib : set solib-search-path xxxx(lib path), 也可以用 info share 命令来查看app 所需的lib。
也可以查看gdb 帮助获得更多的命令,help data (这里有许多设置gdb 的命令) help state (这个可以查看一些状态星系)
symbol-file 应用的执行程序(绝对路径) sharedlibrary 这会从二进制程序文件及其引入的共享库中加载符号
>> 调试
调式 堆栈: bt 可以查看堆栈信息
显示堆栈以及代码信息: bt full
跳到那个栈: f 0
bt f 0 --> 显示栈0 的详细信息
info locals --> 显示 局部变量 info register 显示寄存器信息 info args 显示参数信息
disassemble /m 反汇编带 代码信息
disassemble $pc+12
查看源程序: list 可以查看源码
逐步调式: b 设置断点 clear 清除 r 运行程序
c)在编译没有加-g 参数的调试
这时就需要配合 objdump 和nm 以及ldd 两个命令配合 来找到gdb 报错的地址,再根据nm 和objdump 来找到具体的行号。
objdump --> 把应用程序反编译成 汇编语言
nm -->查看程序符号对应的地址列表
ldd --> 查看程序所需的lib 库
d) 根据Makefile 生成的 符号表 来查看 core dump
$gcc -o your_file.c -Wl,-Map=your_file.map
假如实在调试不出来符号信息, 我们可以尝试用readelf -a app 结合 addr2line -a address -e exclude_bin 来配合找到