15

伙计们,您能否推荐一个工具来发现使用 c++ 构建并在 linux x86_64 下工作的生产多线程服务器上的内存损坏?我目前面临以下问题:每隔几个小时,我的服务器就会因段错误而崩溃,核心转储显示 malloc/calloc 中发生错误,这绝对是某处内存损坏的迹象。

实际上,我已经尝试了一些工具,但运气不佳。这是我到目前为止的经验:

  • Valgrind 是一个很棒的(我什至会说是最好的)工具,但它会大大降低服务器的速度,使其无法在生产中使用。我在舞台服务器上尝试过,它确实帮助我找到了一些与内存相关的问题,但即使在修复它们之后,我仍然会在生产服务器上崩溃。我在 Valgrind 下运行了我的舞台服务器几个小时,但仍然没有发现任何严重的错误。

  • 据说 ElectricFence 是一个真正的记忆猪,但我什至无法让它正常工作。它几乎立即在舞台服务器上随机奇怪的地方出现段错误,而 Valgrind 根本没有显示任何问题。也许 ElectricFence 不能很好地支持线程?...我不知道。

  • DUMA - 与 ElectricFence 相同的故事,但更糟。虽然 EF 生成了带有可读回溯的核心转储,但 DUMA 只向我显示“?????”(是的,服务器肯定是用 -g 标志构建的)

  • dmalloc - 我将服务器配置为使用它而不是标准的 malloc 例程,但是它在几分钟后挂起。将 gdb 附加到进程显示它挂在 dmalloc 的某个地方:(

我逐渐变得疯狂,根本不知道下一步该做什么。我有以下工具可供尝试:mtrace、mpatrol 但也许有人有更好的主意?

我非常感谢在这个问题上的任何帮助。

更新:我设法找到了错误的来源。但是,我在舞台服务器上发现它不是使用 helgrind/DRD/tsan 的生产服务器 - 多个线程之间存在数据竞争,导致内存损坏。关键是使用适当的 valgrind 抑制,因为这些工具显示了太多的误报。仍然我真的不知道如何在生产服务器上发现它而没有任何明显的减速......

4

8 回答 8

7

是的,C/C++ 内存损坏问题很棘手。我也使用了几次valgrind,有时它会显示问题,有时不会。

在检查 valgrind 输出时,不要太快地忽略它的结果。有时花费相当长的时间后,你会发现 valgrind 一开始就给了你线索,但你忽略了它。

另一个建议是比较以前已知的稳定版本的代码更改。如果您使用某种源代码版本控制系统(例如 svn),这不是问题。检查所有与内存相关的函数(例如 memcpy、memset、sprintf、new、delete/delete[])。

于 2009-07-25T20:04:06.880 回答
6

使用 gcc 4.1 和 -fstack-protector-all 开关编译您的程序。如果内存损坏是由堆栈粉碎引起的,这应该能够检测到它。您可能需要使用 SSP 的一些附加参数。

于 2009-07-25T22:11:12.147 回答
4

伙计们,我设法找到了错误的根源。但是,我在使用 helgrind/DRD/tsan 的舞台服务器上发现了它——多个线程之间存在数据竞争,导致内存损坏。关键是使用适当的valgrind 抑制,因为这些工具显示了太多的误报。仍然我真的不知道如何在生产服务器上发现它而没有任何明显的减速......

于 2009-07-31T20:33:11.950 回答
3

你试过-fmudflap吗?(向上滚动几行以查看可用选项)。

于 2009-07-25T22:49:59.417 回答
1

我不确定它是否会捕获您的特定错误,但MALLOC_CHECK_环境变量(malloc手册页)会在默认 Linuxmalloc实现中启用额外检查,并且通常不会产生显着的运行时成本。

于 2009-08-02T18:27:20.023 回答
1

你可以试试 IBM purify,但恐怕不是开源的..

于 2009-07-25T19:57:11.030 回答
1

Google Perftools——它是开源的——可能会有所帮助,请参阅堆检查器文档。

于 2009-07-25T20:15:44.063 回答
1

试试这个: http ://www.hexco.de/rmdebug/ 我广泛使用它,它对性能的影响很小(它主要影响内存量)但分配算法是相同的。它总是被证明足以找到任何分配错误。一旦出现错误,您的程序就会崩溃,并且会有详细的日志。

于 2009-07-30T05:59:42.273 回答