4

我正在编写一个跨计算集群运行的 C 应用程序(使用 condor)。我尝试了许多方法来揭示有问题的代码,但无济于事。

线索:

  • 平均而言,当我在 15 台机器上运行代码 2 天时,我会收到两到三个段错误(信号 11)。
  • 当我在本地运行代码时,我没有遇到段错误。我在家用机器上运行了将近 3 周。

尝试:

  • 我在本地运行 valGrind 中的代码四天,没有出现内存错误。
  • 我通过定义自己的信号处理程序来捕获段错误信号,以便我可以输出一些程序状态。
  • 现在,当发生段错误时,我可以使用回溯打印出当前堆栈。
  • 我可以打印出变量值。
  • 我创建了一个设置为当前行号的变量。
  • 还尝试将代码块注释掉,希望如果问题消失,我会发现段错误。

可悲的是,输出的行号是相当随机的。我不完全确定我可以用堆栈跟踪做什么。我假设它只记录发生段错误的函数的地址是否正确?

怀疑:

  • 我怀疑 condor 用来跨机器移动作业的检查点系统对内存损坏更敏感,这就是为什么我在本地看不到它的原因。
  • 该索引已被错误破坏,并且这些索引导致了段错误。这可以解释段错误发生在相当随机的行号上的事实。

更新

对此进行更多研究,我发现了以下链接:

更新 2

Greg 建议查看 condor 日志并“将段错误与 condor 从检查点重新启动可执行文件的时间相关联”。查看日志,所有段错误都在重新启动后立即发生。当作业从一种类型的机器切换到另一种类型时,所有故障似乎都会发生。

更新 3

段错误是由主机之间的差异引起的,通过将 condor 提交文件中的“requiremets”字段设置为问题完全消失。

可以设置单台机器:

requirements = machine == "hostname1" || machine == "hostname2"

或一整类机器:

requirements = classOfMachinesName

在此处查看要求示例

4

5 回答 5

2

如果可以的话,用调试编译,然后在 gdb 下运行。或者,获取核心转储并将其加载到调试器中。

mpich 有内置调试器,或者你可以购买商业并行调试器。

然后您可以单步执行代码以查看调试器中发生的情况

http://nmi.cs.wisc.edu/node/1610

http://nmi.cs.wisc.edu/node/1611

于 2010-09-10T01:54:57.947 回答
2

当您的段错误发生时,您可以创建核心转储吗?然后,您可以调试此转储以尝试找出代码崩溃时的状态。

看看是什么指令导致了故障。它甚至是一个有效的指令还是你试图执行数据?如果有效,它试图访问什么内存?这个指针是从哪里来的。您需要缩小故障位置(堆栈损坏、堆损坏、未初始化的指针、访问无效内存)。如果是损坏,请查看损坏区域中是否有任何迹象数据(指向符号的指针、看起来像结构中的某些东西的数据……)。您的内存分配器可能已经内置了调试某些损坏的功能(参见MALLOC_CHECK_Linux 或MallocGuardEdgesMac OS)。这些情况的一个常见情况是使用已释放 () 的内存,因此记录您的 malloc() / free() 对可能会有所帮助。

于 2010-09-10T01:56:49.400 回答
1

如果您使用 condor_compile 工具将您的代码与 condor 检查点代码重新链接,它会做一些与普通链接不同的事情。最重要的是,它静态链接您的代码,并使用它自己的 malloc。另一个很大的不同是,condor 将在一台外国机器上运行它,那里的环境可能与您预期的会导致问题的环境大不相同。

condor_compile 生成的可执行文件可以在 condor 系统之外作为独立的二进制文件运行。如果您在本地运行从 condor_compile 发出的二进制文件,在 condor 之外,您还会看到段错误吗?

如果没有,您能否将段错误与 condor 从检查点重新启动可执行文件的时间关联起来(用户日志会告诉您何时发生这种情况)。

于 2010-09-15T00:58:14.060 回答
0

你已经尝试了我想的大部分。我建议的唯一另一件事是开始添加大量日志记录代码,并希望您可以缩小错误发生的范围。

于 2010-09-10T01:39:38.107 回答
0

你没有说的一件事是你有多大的灵活性来解决这个问题。例如,您能否让系统停止并运行您的应用程序?解决这些崩溃问题有多重要?

我假设大多数情况下你都是这样做的。这可能需要大量资源。

短期步骤是放置每个变量的大量“断言”(半手写),以确保它在您不想要的时候没有改变。当您经历长期过程时,这可以继续起作用。

长期——尝试在两个集群上运行它(可能是你的家用计算机和一个虚拟机)。你还看到段错误吗?如果不增加集群大小,直到您开始看到段错误。

以最低配置运行它(以获得段错误)并记录所有输入直到崩溃。使用您记录的输入自动运行系统,并对其进行调整,直到您能够以最少的输入始终如一地发生崩溃。

那时环顾四周。如果您仍然找不到错误,那么您将不得不再次询问您在这些运行中收集的一些额外数据。

于 2010-09-10T03:07:59.047 回答