我能把Valgrind memcheck输出中的"可能丢失"看作是"肯定丢失"吗?
可能丢失或"可疑": 找到了指向块内部的指针。该指针可能最初指向了开头并被移动,也可能完全无关。 Memcheck认为这样的块是"可疑的",因为不清楚是否仍存在对它的指针。
肯定丢失或"泄漏": 最坏的情况是找不到指向该块的指针。该块被归类为"泄漏",因为程序员不可能在程序退出时释放它,因为没有指向它的指针。这很可能是程序中在较早时刻丢失指针的症状。
我能把Valgrind memcheck输出中的"可能丢失"看作是"肯定丢失"吗?
可能丢失或"可疑": 找到了指向块内部的指针。该指针可能最初指向了开头并被移动,也可能完全无关。 Memcheck认为这样的块是"可疑的",因为不清楚是否仍存在对它的指针。
肯定丢失或"泄漏": 最坏的情况是找不到指向该块的指针。该块被归类为"泄漏",因为程序员不可能在程序退出时释放它,因为没有指向它的指针。这很可能是程序中在较早时刻丢失指针的症状。
我建议将可能丢失的情况视为确实丢失的一样严重。换句话说,修复你的代码直到没有任何丢失。
当你使用保存数组的指针遍历数组时,可能会发生可能丢失的情况。虽然你知道可以通过减去索引来重置指针,但valgrind无法确定这是编程错误还是你故意这样做。因此,它会发出警告。
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char** argv) {
char* s = "string";
// this will allocate a new array
char* p = strdup(s);
// move the pointer into the array
// we know we can reset the pointer by subtracting
// but for valgrind the array is now lost
p += 1;
// crash the program
abort();
// reset the pointer to the beginning of the array
p -= 1;
// properly free the memory for the array
free(p);
return 0;
}
编译
$ gcc -ggdb foo.c -o foo
Valgrind报告
$ valgrind ./foo
...
==31539== Process terminating with default action of signal 6 (SIGABRT): dumping core
==31539== at 0x48BBD7F: raise (in /usr/lib/libc-2.28.so)
==31539== by 0x48A6671: abort (in /usr/lib/libc-2.28.so)
==31539== by 0x10917C: main (foo.c:14)
==31539==
==31539== HEAP SUMMARY:
==31539== in use at exit: 7 bytes in 1 blocks
==31539== total heap usage: 1 allocs, 0 frees, 7 bytes allocated
==31539==
==31539== LEAK SUMMARY:
==31539== definitely lost: 0 bytes in 0 blocks
==31539== indirectly lost: 0 bytes in 0 blocks
==31539== possibly lost: 7 bytes in 1 blocks
==31539== still reachable: 0 bytes in 0 blocks
==31539== suppressed: 0 bytes in 0 blocks
...
如果你移除 abort()
,那么 Valgrind 就不会报告有任何内存泄露了。没有 abort 函数,指针将返回数组的开头并且内存将被正确释放。
这是一个微不足道的例子。在足够复杂的代码中,指针能否返回内存块的开头已经不再明显。代码的其他部分的更改可能导致 可能丢失 变成 绝对丢失。这就是为什么你应该关心 可能丢失 的原因。
*s = 'S'
是未定义行为。它可能会导致segmentation fault,也可能会改变s
指向的字符串,或者什么都不做,甚至会使编译器优化整个程序(例如,取决于操作系统和编译器)。 (我宁愿调用可移植的std :: terminate()
。) - Arne Vogelabort()
更新了代码。我认为这是 C 语言中等价于std::terminate()
的函数。 - Lesmana