我面临着一个非常聪明的内存损坏在我的C应用程序。高负载时发生损坏。所以我尝试了purify,valgrind,mprotected,我也试着写我自己的简单的保护机制。
Purify/Valgrind-没有帮助,因为它降低了我的应用程序的性能,并且问题没有重现。mprotected用法只是将损坏移动到其他内存位置。(因为它需要将内存与页面大小对齐)。
我的简单保护机制不起作用,因为它也降低了性能。如何在不降低性能的情况下调试应用程序?
z4bn682m1#
如果你有64位的,你可以使用一个定制的malloc(),它总是执行mmap(),一个定制的free(),它执行munmap(),另一个mmap(),在同一个内存上。用互斥锁保护这些东西,以避免致命的竞争条件。这会改变行为,使其在第一次访问释放的内存时出错。如果找不到,调整自定义malloc(),将分配的缓冲区在mmapped区域中移动到尽可能高的位置。注意,在32位中不能这样做,因为这会疯狂地消耗地址空间。
malloc()
mmap()
free()
munmap()
fwzugrvs2#
Purify/Valgrind-没有帮助,因为它降低了我的应用程序的性能,并且问题没有重现。读到这里,我相信您不仅遇到了内存损坏,而且遇到了一个或多个争用条件。所以我会给你第一次运行helgrind来寻找竞争条件的经验。但是如果你使用std::atomic,helgrind并不知道内存排序。在这种情况下,它会报告误报,或多或少是不可用的。对于这种情况,我不知道任何检查内存排序的工具,这是目前的一个大问题。如何在不降低性能的情况下调试应用程序?问题是:为什么你的失败取决于性能?你有并行的I/O或运行多个任务/线程吗?如果是这样,降低任务或线程或I/O的速度,也许你可以强迫错误上升。减慢其他线程/任务速度的提示:在linux上,你可以将一个线程/任务绑定到一个cpu/内核上,并且你可以通过在这个内核上添加多个"stopper"任务来消耗更多的能量。我知道如果你有调试工具的话,发现已经消失的bug是一场噩梦。但是我们真的帮不上忙,因为我们没有什么可以看的...所以这有点像在看水晶球!
std::atomic
vuktfyat3#
使用消毒剂:在编译标志上添加-fsanitize=address或-fsanitize=thread,它可能会指出缺陷。您也可以添加-O0来删除优化(更好的回溯),以及添加-g来在二进制文件中保留符号/调试信息。
-fsanitize=address
-fsanitize=thread
-O0
-g
3条答案
按热度按时间z4bn682m1#
如果你有64位的,你可以使用一个定制的
malloc()
,它总是执行mmap()
,一个定制的free()
,它执行munmap()
,另一个mmap()
,在同一个内存上。用互斥锁保护这些东西,以避免致命的竞争条件。这会改变行为,使其在第一次访问释放的内存时出错。如果找不到,调整自定义
malloc()
,将分配的缓冲区在mmapped区域中移动到尽可能高的位置。注意,在32位中不能这样做,因为这会疯狂地消耗地址空间。
fwzugrvs2#
Purify/Valgrind-没有帮助,因为它降低了我的应用程序的性能,并且问题没有重现。
读到这里,我相信您不仅遇到了内存损坏,而且遇到了一个或多个争用条件。
所以我会给你第一次运行helgrind来寻找竞争条件的经验。但是如果你使用
std::atomic
,helgrind并不知道内存排序。在这种情况下,它会报告误报,或多或少是不可用的。对于这种情况,我不知道任何检查内存排序的工具,这是目前的一个大问题。如何在不降低性能的情况下调试应用程序?
问题是:为什么你的失败取决于性能?你有并行的I/O或运行多个任务/线程吗?如果是这样,降低任务或线程或I/O的速度,也许你可以强迫错误上升。
减慢其他线程/任务速度的提示:在linux上,你可以将一个线程/任务绑定到一个cpu/内核上,并且你可以通过在这个内核上添加多个"stopper"任务来消耗更多的能量。
我知道如果你有调试工具的话,发现已经消失的bug是一场噩梦。但是我们真的帮不上忙,因为我们没有什么可以看的...所以这有点像在看水晶球!
vuktfyat3#
使用消毒剂:
在编译标志上添加
-fsanitize=address
或-fsanitize=thread
,它可能会指出缺陷。您也可以添加
-O0
来删除优化(更好的回溯),以及添加-g
来在二进制文件中保留符号/调试信息。