C 如何在主进程之前调试崩溃?

C 如何在主进程之前调试崩溃?,c,gdb,C,Gdb,我的程序静态链接到许多库,在进入gdb中的main之前崩溃。我如何诊断问题是什么?< p>我在C中没有遇到过这个问题,但是如果你链接到C++库,静态初始化可能崩溃。通过在静态范围变量的构造函数中使用断言,可以轻松创建它 开始逐个取出库,直到它停止崩溃。 然后检查罪魁祸首。它可能会崩溃,因为某些组件抛出异常,但由于尚未输入main(),因此没有人捕获它。在引发异常时设置断点: catch throw run (如果第一次启动时catch-throw不起作用,请运行一次,让它加载动态库,然后执行c

我的程序静态链接到许多库,在进入gdb中的main之前崩溃。我如何诊断问题是什么?

< p>我在C中没有遇到过这个问题,但是如果你链接到C++库,静态初始化可能崩溃。通过在静态范围变量的构造函数中使用断言,可以轻松创建它

开始逐个取出库,直到它停止崩溃。
然后检查罪魁祸首。

它可能会崩溃,因为某些组件抛出异常,但由于尚未输入
main()
,因此没有人捕获它。在引发异常时设置断点:

catch throw
run

(如果第一次启动时
catch-throw
不起作用,请运行一次,让它加载动态库,然后执行
catch-throw
并再次运行)。

很有可能
LD\u-DEBUG
可以帮助您。试试这个:
LD\u DEBUG=all./a.out
。这将允许您在程序崩溃时轻松识别正在加载的库

(编辑:如果不清楚,
a.out
指的是一个通用二进制文件——在本例中,将其替换为可执行文件的名称)

编辑2:

要澄清的是,
LD_DEBUG
是一个环境变量,当程序开始执行时,动态链接器会检查它。如果将
LD_DEBUG
设置为某个值,则动态链接器将输出有关在程序执行、符号绑定等过程中加载的动态库的大量信息

首先,在您的机器上执行以下操作:

LD_DEBUG=help ls
您将看到系统上列出的
LD_DEBUG
的有效选项。最详细的设置是
all
,它将显示所有可用信息


现在,要使用它就像
ls
示例一样简单,只需用程序名替换
ls
。使用LD_DEBUG不需要gdb,因为它是仅由动态链接器提供的功能,而不是由gdb提供的功能。

本文给出了答案,您必须在crt0启动代码的main之前设置断点:

如果可以,动态链接程序,而不是静态链接,并遵循@denniston.t。也许从动态链接器调试跟踪将有助于解决此问题。

starti

starti
在执行第一条指令时中断,另请参见:

如果您的GDB不够新,另一种选择是:

break _start
如果您知道入口点方法的名称是
\u start
,或者:

info files
搜索
入口点

 Entry point: 0x400440
并运行:

 break *0x400440

TODO:了解如何使用调试符号编译
crt*
对象,并逐步使用它们:

真的吗?这并不特别现实。有些程序很大,删除一个库意味着许多引用现在将不再链接。@Joe是的,有时候你不得不做一些困难的事情。你有更好的建议,或者使用<代码> LDYDEXGUG/<代码>作为帮助完成相同的事情的捷径(见我的答案)。这是令人恼火的,而且花费了很长时间,但是这就是我所做的。你能在这里发布崩溃的回溯吗?@ KS1322:如果他有回溯,他可能不会问如何诊断问题:-),C,而不是C++。gdb返回:“函数”\uuuucxa\uthrow“未定义”。我如何确切地添加它?这看起来不像gdbfunction@denniston.t,
LD_DEBUG
用于调试共享库,但这里的程序是静态链接的。如果bug在静态库中,那就没用了。@ks1322:哎呀,我错过了问题的这一部分。谢谢你指出这一点。你能解释一下吗?很可能是静态链接库本身链接了其他库dynamically@chacham15:我已经更新了我的答案,并提供了更多详细信息:它不是gdb命令,而是在执行程序时指定的环境变量。函数“\uu libc\u start\u main”未定义。您的程序将具有类似的内容。通过在可执行文件上运行readelf-h,您可以了解实际的执行入口点是什么。您可以在它显示的入口点地址上设置断点。问题是,一旦它停止,我就没有办法“遍历库”。