我知道valgrind以允许捕获segfaults的方式跟踪内存。但是,为什么不捕获以下segfault?
int main() {
char *x = calloc(16, 1);
char *y = calloc(16, 1);
x[80] = 'c';
y[-80] = 'c';
printf("%c %cn", *x, *y);
return 0;
}
它不应该在堆中捕捉到限制的访问吗?根据Valgrind的文档:
But it should detect many errors that could crash your program (eg. cause a segmentation fault).
我认为您正在赋予Valgrind,而不是超出可能的力量。
它将尝试检测各种错误的错误并向您报告,但也无法检测所有错误,即使在尝试检测的某些错误类别中。
在这种情况下,您要处理的是一个界限写入数组,如果Valgrind设法捕获它,将报告为"无效的写入"错误。通过跟踪哪些地址为"有效",因为它们是已知堆块的一部分。
问题是,如果您超过数组的开始或结束太远,您实际上可能会带有一个地址,该地址是相邻块中的有效地址,因此,该地址看起来绝对不错。为了减少这种情况的机会,Valgrind会增加一个块的每一侧的填充区域(称为"红色区域"),但默认情况下只有16个字节。
如果您使用--redzone-size=128
选项增加了红色区域大小,那么您会发现Valgrind确实检测到此程序中的错误。
对我有用:
==24344== Memcheck, a memory error detector.
==24344== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et al.
==24344== Using LibVEX rev 1854, a library for dynamic binary translation.
==24344== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP.
==24344== Using valgrind-3.3.1-Debian, a dynamic binary instrumentation framework.
==24344== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et al.
==24344== For more details, rerun with: -v
==24344==
==24344== Invalid write of size 1
==24344== at 0x8048419: main (testValgrind.c:5)
==24344== Address 0x418f078 is 0 bytes after a block of size 16 alloc'd
==24344== at 0x4021E22: calloc (vg_replace_malloc.c:397)
==24344== by 0x804840F: main (testValgrind.c:3)
==24344==
==24344== Invalid write of size 1
==24344== at 0x8048422: main (testValgrind.c:6)
==24344== Address 0x418f018 is 16 bytes before a block of size 16 alloc'd
==24344== at 0x4021E22: calloc (vg_replace_malloc.c:397)
==24344== by 0x80483F8: main (testValgrind.c:2)
==24344==
==24344== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 12 from 1)
==24344== malloc/free: in use at exit: 32 bytes in 2 blocks.
==24344== malloc/free: 2 allocs, 0 frees, 32 bytes allocated.
==24344== For counts of detected errors, rerun with: -v
==24344== searching for pointers to 2 not-freed blocks.
==24344== checked 58,940 bytes.
==24344==
==24344== LEAK SUMMARY:
==24344== definitely lost: 32 bytes in 2 blocks.
==24344== possibly lost: 0 bytes in 0 blocks.
==24344== still reachable: 0 bytes in 0 blocks.
==24344== suppressed: 0 bytes in 0 blocks.
==24344== Rerun with --leak-check=full to see details of leaked memory.