代码执行分配所有内存,直到它可能在代码初始化时被OOM(linux)杀死.调试这样一个问题的想法



我在一些代码上遇到了一个非常奇怪的问题。我正在尝试调试我在linux集群上编译的C++/Fortran代码。当我运行它时,屏幕上没有任何输出,代码崩溃。我可以用top看到我的应用程序启动并分配内存,直到它耗尽(128GB(并被内核OOM杀死。我尝试使用调试器,并在main上设置了一个断点,但仍然得到了相同的行为。因此,我假设错误发生在进入main之前,所以我假设它与静态/全局数据初始化或类初始化有关。我已经尝试了几个编译器优化选项,在使用-O0时取得了一些成功,但对于任何其他的优化级别,它们都会崩溃。具有不同优化选项的不同行为向我表明,代码中也存在问题,例如未定义的行为,但我也不知道如何处理。

我知道这个问题不是一个理想的问题,我没有一个最低限度的工作例子。尽管代码在公共存储库中可用,但编译起来很困难,并且您需要不公开的输入文件来运行它。

到目前为止,我已经做到了这一点。我不知道如何处理这个bug,所以任何想法或建议都非常受欢迎,我会尽力回答任何问题。

谢谢!

第一步是用strace验证它不是晚期execve故障。这种故障表现为execve之后的立即信号,而在execve之后没有针对相同进程的任何系统调用。

发生这种情况是因为execve不是原子:如果它已经开始用新的进程映像替换当前进程映像,但之后失败,它不会返回错误(因为它可以返回的原始进程映像已经不见了(,而是用信号终止进程。信号随内核版本而变化(如果我没记错的话,可以是SIGKILLSIGSEGV(。如果发生这种情况,就意味着你的程序可能有一些非常大的全局变量。它们应该作为带有readelf -lW的大LOAD段和带有readelf -SW的大数据段可见。

如果不是后期execve失败,希望程序初始化运行的时间足够长,以便您可以在调试器和^C下运行它,或者将其发送到SIGINT,并以这种方式进行回溯,以查看它在做什么。如果这不起作用,您可以在__libc_start_main上设置一个断点,并逐步通过它,直到它通过init函数指针调用主程序ELF构造函数。对于共享对象中的ELF构造函数,您需要在_dl_init上设置断点(对于未来的glibc版本,可能从glibc 2.33或2.34开始;它们将不再从__libc_start_main运行主程序ELF构造函数(。

最新更新