gdb调试的三种类型
- gdb filename
- gdb filename corename
- gdb attach pid
命令记录
show language, set language c++
bt, bt full
- f
可以跳转到某个栈中位置 - info locals 显示当前调用栈的所有变量
- info register 显示当前调用栈的寄存器值,主要是查看地址
thread apply all bt
- info threads 可以查看所有线程的信息
- 第一列为 ID, LWP XXX 是线程号,thread ID会跳转到某个线程上
- thread
可以具体跳转到某个线程 - info args
- 打印出当前函数的参数名及其值
- disassemble 显示指令
- set print pretty 设置格式化输出
- print *smart-pointer._M_ptr 打印智能指针内容
- p leval1.leval2 打印leval1中leval2结构
- 如果leval2是STL容器,在不使用辅助脚本的情况下,只能全部元素打印出来;使用辅助脚本可能也不支持打印std::unordered_map中某个元素值
- 打印std::unordered_map中某元素值,值类型为智能指针,智能指针指向的类型也是智能指针
- 打印出unordered_map中所有元素值,其中一条:[384953685] = std::shared_ptr (count 1, weak 0) 0x7f7dfb673778,这个地址为智能指针所指向内容的地址
- p *(level1*)0x7f7dfb673778,打印上述地址的内容,level1为智能指针指向的类型,得到结果:$5 =
- p *(leval2*)(*(level1*)0x7f7dfb673778) 或者 p *(CDocumentData*)0x7f8651ef2418,打印出二级智能指针指向的内容
- handle SIGSEGV nostop
- 使用gdb启动调用了libjvm.so的程序时需要忽略 SIGSEGV 信号
- 启动 gdbserver
- gdbserver IP:PORT executable
- 连接 gdbserver
- gdb executable 之后 target remote IP:PORT
core dump
相关配置
参考
man 5 core
-
开关:
ulimit
-
文件格式与路径:
echo '/target_path/core.%p' > /proc/sys/kernel/core_pattern
mini core
core文件是调试问题的关键,但有时服务产生的core文件非常大,生成过程缓慢并且占用大量空间,线上环境很可能是不允许的。那么可以在服务中捕获异常信号,通过调用backtrace/backtrace_symbols函数生成函数调用栈并保存下来,从而避免超大core文件引起磁盘报警,但这种方案无法将变量等数据保存下来,对排查问题有些不友好
问题记录
-
memcpy时越界,覆盖了其他内存
- 通过gdb filename corename,打印出core的线程栈,分析并打印局部变量
-
指令集错误
- Program terminated with signal 4, illegal instruction,即不支持的指令集
-
signal SIGBUS 7, Bus error
- 由于mmap之后,源文件被改变(内容变少),造成访问越界
参考资料
gdb调试之基础篇
gdb调试之实用技巧篇
Linux GDB core高级调试
善用GDB 调试一些函数栈被毁坏的问题
段错误调试神器 - Core Dump详解
由mmap引发的SIGBUS
排错经历:全局变量被多次析构
使用linux的GDB打印STL容器数据
打印STL容器中的内容
Strange sigsegv while calling java code from c++ through jni
Linux backtrace()详细使用说明,分析Segmentation fault
linux进程内存结构&coredump filter
How to make backtrace()/backtrace_symbols() print the function names?
how-to-get-more-detailed-backtrace
关于gdb调试core文件总是一堆问号的问题