我的程序在访问gdb中的main之前静态链接到许多库和崩溃。我如何诊断问题是什么?
开始逐一取出库,直到它停止崩溃。然后检查罪魁祸首。
这是一个很好的选择,LD_DEBUG
可以帮助你。试试这个:LD_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之前设置一个断点:Using GDB without debugging symbols on x86?
我没有在C中遇到过这个问题,但如果你链接到c ++库,静态初始化就会崩溃。您可以通过在静态范围变量的构造函数中使用断言来轻松创建它。
它可能会崩溃,因为一些组件抛出一个异常,没有人抓住它,因为还没有输入main()
。在抛出异常时设置断点:
catch throw
run
(如果catch throw
第一次启动它时不起作用,运行一次让它加载动态库,然后再执行catch throw
并再次运行)。
starti
starti
在执行的第一条指令中断开,参见:Stopping at the first machine code instruction in GDB
如果你的GDB不够新,那么另一种选择:
break _start
如果您知道入口点方法的名称是_start
,或者:
info files
搜索Entry point
:
Entry point: 0x400440
并运行:
break *0x400440
TODO:了解如何使用调试符号编译crt*
对象并进入它们:How to compile my own glibc C standard library from source and use it?
如果可以,请动态链接您的程序而不是静态链接,并关注@denniston.t answer。也许从动态链接器调试跟踪将有助于解决此问题。