如何让GDB告诉我哪个地址导致了段错误?

59

我想知道我的程序是否在访问空指针或陈旧的内存。

回溯看起来像这样:

程序接收到信号SIGSEGV,分段错误。
[切换到线程0x2b0fa4c8(LWP 1333)]
0x299a6ad4在/lib/libpthread.so.0中的pthread_mutex_lock()处。
(gdb) bt
#0 0x299a6ad4在/lib/libpthread.so.0中的pthread_mutex_lock()处。
#1 0x0058e900在??()处。
2个回答

95

使用 GDB 7 或更高版本,您可以检查在信号发生时填充的 $_siginfo 结构,并确定故障地址:

(gdb) p $_siginfo._sifields._sigfault.si_addr
如果显示 (void *) 0x0 (或者一个小数字),那么你就有一个空指针解引用错误。

(gdb) p $_siginfo $1 = void 我猜在这个架构上不支持siginfo :( - nornagon
4
使用命令ptype $_siginfo查看结构体中还有哪些内容。 - To1ne

-4
在GDB下运行您的程序。当出现段错误时,GDB将通知您程序的行和语句,以及变量及其关联地址。
您可以使用GDB中的“print”(p)命令检查变量。如果崩溃发生在库调用中,您还可以使用“frame”系列命令来查看相关的堆栈帧。

2
@nornagon:bt命令将显示一个回溯,让你看到故障发生时自己的代码所处的位置。 - caf
2
是的,我知道,但这仍然没有帮助——它在一个带有多个参数的库函数调用中,我不知道哪个参数导致了段错误。 - nornagon
在可能出错的地方加上监视器;在你怀疑会发生信号错误的地方加上断点,并逐步观察重要变量... - ShinTakezou
3
@nornagon:你的回溯信息(backtrace)有点可疑——在调用参数之前,你可能已经发生了栈破坏。如果通过代码步进(“n”和“s”)无法找出问题,那么现在该使用valgrind来解决了。 - Yann Ramin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接