如何在Linux上调试内存损坏问题

6
我面临的问题是在C应用程序中存在非常聪明的内存损坏。
损坏发生在高负载下。
因此,我尝试了Purify、Valgrind、mprotected,并尝试编写自己的简单保护机制。
Purify / Valgrind - 由于它们降低了我的应用程序的性能并且问题没有复现,所以没有帮助。
mprotected 的使用只是将损坏移动到其他内存位置。(因为它需要对齐内存到页面大小)
我的简单保护机制不起作用,因为它也会降低性能。
如何在不降低性能的情况下调试我的应用程序?

4
如果Valgrind找不到它,我会感到惊讶。 - Mitch Wheat
高负载时会发生数据损坏。你怎么知道?另外,监视进程的VSIZ+RSS。可能是因为你正在泄漏内存。 - wildplasser
内存损坏会如何表现?您的应用程序是单线程还是多线程?您的硬件在压力测试下稳定吗? - Maxim Egorushkin
内存损坏会表现为什么样的情况?您的应用程序是单线程还是多线程的?您的硬件在压力测试下稳定吗? - undefined
3个回答

0

使用消毒剂:

在编译标志中添加-fsanitize=address-fsanitize=thread,它很可能会指出缺陷。

您还可以添加-O0以删除优化(获得更好的回溯)和-g以保留二进制文件中的符号/调试信息。


0
如果您使用64位系统,可以使用自定义的malloc()函数,它始终执行mmap()操作,并使用自定义的free()函数在同一内存上执行munmap()和另一个mmap()操作。请使用互斥锁来保护这些内容,以避免致命的竞态条件。这将更改行为,使其在第一次访问已释放内存时出现故障。
如果找不到内存,请调整自定义的malloc()函数,将分配的缓冲区尽可能地移动到mmapped区域的高处。
请注意,32位系统无法执行此操作,因为这会浪费大量地址空间。

0
Purify/Valgrind并不能解决问题,因为它降低了我的应用程序的性能,并且问题没有被重现。当阅读这些时,我相信你不仅有内存损坏,还有一个或多个竞态条件。因此,我会给你一个提示,首先使用 helgrind查找竞态条件。但是,如果你使用std::atomic,helgrind意识不到内存排序,会报告错误结果,基本上是无法使用的。对于这种情况,我不知道任何检查内存排序的工具,这是目前的一个大问题。
“如何在不降低性能的情况下调试我的应用程序?”问题是:为什么你的失败取决于性能?你是否在并行进行I/O或运行多个任务/线程?如果是这样,降低这些任务或线程的速度或I/O速度,也许可以强制出现错误。
减慢其他线程/任务的提示: 在Linux上,您可以将一个线程/任务绑定到一个CPU/核心,并且通过在该核心上添加多个“停止器”任务,您有希望可以消耗更多的电源在单个核心上。 taskset。 您还可以使用 -O0 或其他黑科技编译代码的特殊部分。
我知道如果您安装了调试工具,则很难找到已消失的错误。 但是我们真的无法提供帮助,因为我们没有什么可以查看的...所以这有点像读水晶球!

这不是C++ -- 没有 std::atomic - S.S. Anne
1
@JL2210:我不知道为什么我看到这个问题,因为它是5年前的。也许现在已经使用c++了 :-) 这个问题对于c++和c来说都是通用的。任何发现这个晚回答有用的人也可能会发现原子提示有用。但是,是的,c没有原子操作 :-) - Klaus
Joshua(其他回答者之一)通过回答将其推到“活跃”状态。 - S.S. Anne
这个从来没有被标记为[c++]。 - S.S. Anne

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接