如何调试仅在负载巨大时出现的错误?

时间:2017-10-03 09:15:09

标签: c debugging gdb heisenbug

我们目前正在开发C中的集群管理器软件。如果有几个节点连接到管理器,它可以完美运行,但如果我们使用一些工具模拟1000个节点来连接管理器,它有时会以意想不到的方式工作。 / p>

如何调试此类错误?它仅在负载(连接/节点)很大时出现?

如果我使用gdb逐步调试,应用程序永远不会出现故障。

2 个答案:

答案 0 :(得分:4)

遗憾的是,调试器对于调试并发/加载问题的用处不大。

继续添加日志/ printfs,通过负载测试触发问题,然后尝试使用更多日志/ printfs缩小范围。重复。

触发错误的速度越快,收敛速度就越快。在添加日志时也更喜欢经典的“二分法”/“二分搜索”技术 - 尝试每次至少缩小一半的区域。

答案 1 :(得分:4)

  

如何调试此类错误?

通常,您希望至少使用以下技术:

  1. 确保代码编译并链接而不发出警告。 -Wall是一个良好的开端,但-Wextra更好。
  2. 确保应用程序具有设计日志记录和跟踪功能,可以打开或关闭,并且具有足够的详细信息来调试这些问题,并且开销很低。
  3. 确保代码具有良好的单元测试覆盖率。
  4. 确保测试是清洁剂清洁。
  5.   

    在valgrind检查中也没有警告。

    目前尚不清楚您是否只是在Valgrind下运行目标应用程序,或者您是否也进行了单元测试,而且测试是Valgrind-clean。您是否已经观察到Valgrind下的应用程序错误行为还不清楚。

    Valgrind曾经是堆和非实体化内存问题的最佳工具,但在2017年已不再是这种情况。

    基于编译器的AddressThreadMemory清理程序会捕获更多类错误(例如全局和堆栈溢出以及数据争用),您应该在下运行单元测试所有这些。

    如果上述所有问题仍未找到问题,您可以运行使用消毒剂检测的真实应用程序。

    最后,有GDB tracingsystemtap等工具 - 它们更难学,但却给你很大的力量。概述here