查找特定内存位置的数据上次修改的时间?(C、gcc、gdb、valgrid、clang?)



我有一个讨厌的segfault,它已经困扰了我一段时间了。它与代码从32位迁移到64位有关,但这是一个偶然的错误,很难追踪。

我想知道——有没有任何工具(首选Linux、FOSS)可以用来从segfault进行追溯,找到我的代码中非法(越界)指针的值分配到哪里?

例如,如果我通过尝试读取变量int *a所指向的int值(该值已在代码中的其他地方分配)来获得segfault,那么我如何在代码中分配该值的位置找到

这似乎是一种可以用clang/llvm做的事情,但我真的不知道该去哪里看。我想这样的想法真的不能用gdb或valgrind来完成,因为IFAIK他们没有办法在程序执行期间存储所需的信息。

任何人得到的建议都将不胜感激!

编辑: 经过大量挖掘,我发现了我一直在寻找的错误。基本上,一个"unsigned long*"被强制转换为"int*",从而以某种方式抑制了警告(http://ascend4.org/b564)。然而,问题仍然存在,因为我的错误搜索非常手动和乏味:如果我的程序中有一个变量,我如何追溯到是什么序列/链/树的语句导致它取当前值是否有任何工具可以自动执行此操作?这包括将参数传递给函数、赋值语句(包括通过取消引用的指针进行赋值)等。

内存断点(GDB文档中的观察点)听起来像是要走的路。使用-g进行编译以调试符号,然后放置一个内存写入断点,如下所示:

print &a
watch *0xdeadbeef

如果您也想包含读取内容,可以使用awatch。查看GDB文档了解更多信息。这样,您应该能够在分段故障发生之前跟踪最后一次写入。

对于此类问题,您应该使用的工具是valgrind。例如,使用Valgrind尝试以下代码:

char *str = malloc(10);
str[10] = '';

它打印:

==14272== Invalid write of size 1
==14272==    at 0x80483E4: main (in /path/to/a.out)
==14272==  Address 0x4025032 is 0 bytes after a block of size 10 alloc'd
==14272==    at 0x4005BDC: malloc (vg_replace_malloc.c:195)
==14272==    by 0x80483D8: main (in /path/to/a.out)

但是,如果valgrind不适用,则可以选择用mmap替换malloc,使分配的块开始之前的字节或分配的块结束之后的字节未映射。因为块大小通常不是页面大小的倍数,所以只能选择其中一个选项,而不能同时选择两个选项。但您可以分别使用"不映射开始"one_answers"不映射结束"策略来处理问题,以捕获这两种错误。

不幸的是,关于如何用mmap替换malloc的代码对于这个答案来说太长了。

相关内容

  • 没有找到相关文章

最新更新