我正在编写一个在应用程序集群中运行的C应用程序(使用condor)。我已经尝试了很多方法来揭示有问题的代码,但无济于事。
线索:
尝试:
可悲的是,输出的行号相当随机。我不完全确定我能用stacktrace做什么。假设它只记录发生段错误的函数的地址,我是否正确?
猜疑:
更新
再研究一下,我发现了以下链接:
LibSegFault - 用于自动捕获和打印有关segfaults的状态数据的库。
Stack unwinding (stack trace) with GCC有关捕获段错误的教程,并获取违规指令的行号。
更新2
Greg建议查看condor日志并“将segfaults关联到condor从检查点重新启动可执行文件”。查看日志后,segfaults会在重新启动后立即发生。当作业从一种类型的机器切换到另一种类型时,似乎会发生所有故障。
更新3
段错误是由主机之间的差异引起的,通过在condor提交文件中设置'requiremets'字段使问题完全消失。
可以设置单独的机器:
requirements = machine == "hostname1" || machine == "hostname2"
或整类机器:
requirements = classOfMachinesName
请参阅要求示例here
答案 0 :(得分:2)
如果可以,请使用调试进行编译,然后在gdb下运行。 或者,将核心转储并加载到调试器中。
mpich有内置调试器,或者你可以购买商用并行调试器。
然后,您可以单步执行代码以查看调试器中发生的事情
答案 1 :(得分:2)
当您的段错误发生时,您可以创建核心转储吗?然后,您可以调试此转储以尝试在崩溃时找出代码的状态。
看看导致故障的指令。它甚至是一个有效的指令还是你试图执行数据?如果有效,它试图访问什么内存?这个指针来自哪里。您需要缩小故障的位置(堆栈损坏,堆损坏,未初始化的指针,访问无效的内存)。如果它是一个腐败,看看是否在损坏的区域中有任何告诉数据(指向符号的指针,看起来像你的结构中的数据,......)。您的内存分配器可能已具有内置功能来调试某些损坏(请参阅Linux上的MALLOC_CHECK_
或Mac OS上的MallocGuardEdges
)。这些的常见情况是使用free()的内存,因此记录malloc()/ free()对可能有所帮助。
答案 2 :(得分:1)
如果您使用condor_compile工具使用condor检查点代码重新链接代码,那么它与普通链接的做法有所不同。最重要的是,它静态链接您的代码,并使用它自己的malloc。另一个很大的区别是,condor会在外国机器上运行它,在那里环境可能与你预期的问题不同。
condor_compile生成的可执行文件可作为condor系统之外的独立二进制文件运行。如果你在condor之外本地运行从condor_compile发出的二进制文件,你还能看到段错误吗?
如果没有,是否可以将段错误关联到condor从检查点重新启动可执行文件时(用户日志会告诉您何时发生这种情况)。
答案 3 :(得分:0)
你已经尝试了我想到的大部分内容。我建议的另一件事是开始添加大量的日志记录代码,并希望你可以缩小发生错误的位置。
答案 4 :(得分:0)
您没有说的一件事是您有多大的灵活性来解决问题。 例如,您是否可以暂停系统并运行您的应用程序? 这些崩溃还有多重要?
我假设大部分时间你这样做。这可能需要大量资源。
短期步骤是对每个变量放置大量“断言”(半手写) 当你不想要它时,确保它没有改变。这可以在您经历长期过程时继续工作。
长期 - 尝试在两个群集(可能是您的家用计算机和VM)上运行它。 你还看到段错误吗?如果在您开始看到段错误之前不增加簇大小。
以最低配置运行它(以获取段错误)并记录所有输入直到崩溃。使用您记录的输入自动运行系统,对其进行调整,直到您能以最小的输入一致地获得崩溃。
此时环顾四周。如果您仍然找不到该错误,那么您将不得不再次询问您使用这些运行收集的一些额外数据。