我的 C 应用程序中面临着非常智能的内存损坏。
高负载时会发生损坏。
所以我尝试了purify、valgrind、mprotected,还尝试编写自己的简单保护机制。
Purify / Valgrind - 没有帮助,因为它降低了我的应用程序的性能并且问题没有重现。
mprotected 使用只会将损坏移动到其他内存位置。 (因为它需要将内存与页面大小对齐)。
我的简单保护机制不起作用,因为它还降低了性能。
如何在不降低性能的情况下调试我的应用程序?
如果您有 64 位,则可以在同一内存上使用始终执行
malloc()
操作的自定义 mmap()
和执行 free()
操作的自定义 munmap()
和另一个 mmap()
。使用互斥体保护这些东西,以避免致命的竞争状况。这会将首次访问已释放内存时出现故障的行为更改为错误。
如果没有找到,请调整自定义
malloc()
,将分配的缓冲区移动到映射区域中尽可能高的位置。
请注意,您不能在 32 位中执行此操作,因为这会疯狂地消耗地址空间。
Purify / Valgrind - 没有帮助,因为它降低了我的应用程序的性能并且问题没有重现。
在阅读本文时,我相信您不仅存在内存损坏,还存在一个或多个竞争条件。
所以我会告诉你先用 helgrind 运行来找到比赛条件。但是如果您使用
std::atomic
,helgrind 并不知道内存排序。在这种情况下,它会报告误报并且或多或少无法使用。对于这种情况,我不知道有任何工具可以检查内存顺序,这目前是一个大问题。
如何在不降低性能的情况下调试我的应用程序?
问题是:为什么你的失败取决于表现?您是否有并行 I/O 或运行多个任务/线程?如果是这样,请降低任务或线程或 I/O 的速度,也许您可以强制引发错误。
减慢其他线程/任务速度的提示: 在 Linux 上,您可以将线程/任务绑定到 cpu/核心,并且您希望通过在该核心上添加多个“停止”任务来消耗该单个核心上的更多电量。 任务集。您还可以使用
-O0
或其他技巧来编译代码的特殊部分。
我知道如果您有调试工具,那么找到消失的错误是一场噩梦。但我们真的帮不上什么忙,因为我们没有什么可看的……所以这有点像解读水晶球!
使用消毒剂:
在编译标志上添加
-fsanitize=address
或 -fsanitize=thread
,它可能会指出缺陷。
您还可以添加
-O0
来删除优化(更好的回溯)和 -g
来将符号/调试信息保留在二进制文件中。