我正在编写一个跨计算集群运行的 C 应用程序(使用 condor)。我尝试了许多方法来揭示有问题的代码,但无济于事。
线索:
- 平均而言,当我在 15 台机器上运行代码 2 天时,我会收到两到三个段错误(信号 11)。
- 当我在本地运行代码时,我没有遇到段错误。我在家用机器上运行了将近 3 周。
尝试:
- 我在本地运行 valGrind 中的代码四天,没有出现内存错误。
- 我通过定义自己的信号处理程序来捕获段错误信号,以便我可以输出一些程序状态。
- 现在,当发生段错误时,我可以使用回溯打印出当前堆栈。
- 我可以打印出变量值。
- 我创建了一个设置为当前行号的变量。
- 还尝试将代码块注释掉,希望如果问题消失,我会发现段错误。
可悲的是,输出的行号是相当随机的。我不完全确定我可以用堆栈跟踪做什么。我假设它只记录发生段错误的函数的地址是否正确?
怀疑:
- 我怀疑 condor 用来跨机器移动作业的检查点系统对内存损坏更敏感,这就是为什么我在本地看不到它的原因。
- 该索引已被错误破坏,并且这些索引导致了段错误。这可以解释段错误发生在相当随机的行号上的事实。
更新
对此进行更多研究,我发现了以下链接:
LibSegFault - 一个用于自动捕获和打印有关段错误的状态数据的库。
使用 GCC 教程中的堆栈展开(堆栈跟踪)捕获段错误并获取违规指令的行号。
更新 2
Greg 建议查看 condor 日志并“将段错误与 condor 从检查点重新启动可执行文件的时间相关联”。查看日志,所有段错误都在重新启动后立即发生。当作业从一种类型的机器切换到另一种类型时,所有故障似乎都会发生。
更新 3
段错误是由主机之间的差异引起的,通过将 condor 提交文件中的“requiremets”字段设置为问题完全消失。
可以设置单台机器:
requirements = machine == "hostname1" || machine == "hostname2"
或一整类机器:
requirements = classOfMachinesName
在此处查看要求示例