空指针解引用最常见,print ptr可快速验证是否为0x0或非法地址;backtrace+frame+info args能准确定位问题参数;x/1bx ptr可检测地址是否真实可读;条件断点可提前拦截异常参数。

用 print 直接查看指针值是否为 0x0 或非法地址
函数崩溃前最常见的是空指针解引用(SIGSEGV),而参数指针是否为空,print 是最快验证方式。程序停在断点或崩溃点后,直接输入:print ptr(假设参数名是 ptr)
如果输出是 $1 = 0x0,基本可判定为空指针;如果输出是类似 $1 = 0xfffffffffffe0000 这种明显非对齐、高位全 1 的地址,大概率是野指针或已释放内存地址。
注意:print 显示的是指针变量本身的值(即地址),不是它指向的内容。想看内容得加 *:print *ptr —— 但一旦 ptr 为空或非法,这步会触发 GDB 报错或卡住,所以务必先确认地址合法再解引用。
崩溃后用 backtrace 定位到具体调用帧,再 frame 切换并 info args
段错误发生后,backtrace(简写 bt)能快速看到调用链,比如输出:#0 process_data (buf=0x0, len=10) at util.c:42#1 main () at main.c:15
这说明 process_data 被调用时传入的 buf 就是 0x0。此时执行:frame 0 —— 切到出问题的栈帧info args —— 列出当前函数所有参数及其值
比手动 print 更稳妥,尤其当参数名不直观、或有重载/宏展开干扰时。
容易忽略的一点:info args 只在当前栈帧有效;如果函数内联或编译优化开启(如用了 -O2),参数可能被优化掉,info args 会显示 “No arguments.”——这时必须退回去检查上一级调用(frame 1)传了什么。
用 x 命令验证指针指向的内存是否可读
指针非空不等于安全。比如指向已 free 的堆内存、或栈上已出作用域的局部变量地址,print *ptr 可能看似成功,但值不可信,甚至导致 GDB 暂停响应。
更底层的验证方式是:x/1bx ptr —— 尝试读取指针地址处 1 字节(b 表示 byte)
如果返回类似 Cannot access memory at address 0x7fffff...,说明该地址不可读,参数虽非空但无效。x/4i ptr —— 若指针本应指向函数,可用此看是否为合法指令地址(需结合符号表判断)。
关键差异:print *ptr 依赖调试信息做类型解析和自动格式化;x 是裸内存读取,绕过类型系统,更适合查“地址本身有没有映射”,也更接近 CPU 真实行为。
条件断点提前拦截异常参数传入
与其等崩溃再查,不如在函数入口设条件断点,把问题拦在发生前:break process_data if buf == 0break process_data if len <br>这样每次调用 <code>process_data 时,GDB 自动检查参数,只在满足条件时暂停。
适用场景:复现周期长、或崩溃发生在深层调用中难以回溯时。但要注意:
– 条件表达式里不能用未定义符号或运行时不可访问的变量
– 如果函数被频繁调用且条件复杂,会影响调试性能
– C++ 成员函数需写成 break ClassName::method if this == 0 验证 this 指针
真正难的不是看出指针为空,而是搞清“为什么传进来就是空”——调用方逻辑缺陷、错误的初始化顺序、多线程竞争修改、或者函数文档没写清参数约束,这些都得结合上下文代码和业务逻辑判断。GDB 只告诉你“是什么”,不解释“为什么”。


















