我有一个这样的程序:
int *number0 = new int;
int main()
{
int *number1 = new int;
}
我认为,这两种内存分配都会引入内存泄漏,尽管只是valgrind抱怨main函数中的number1。为什么呢?
运行此
int *x = new int;
int main()
{
return 0;
}
代码(即没有泄漏,用g++ 4.8.1编译)使用valgrind (3.8.1) with (-v --track-origins=yes --leak-check=full --show-reachable=yes
)我得到:
==34301==
==34301== HEAP SUMMARY:
==34301== in use at exit: 4 bytes in 1 blocks
==34301== total heap usage: 1 allocs, 0 frees, 4 bytes allocated
==34301==
==34301== Searching for pointers to 1 not-freed blocks
==34301== Checked 189,064 bytes
==34301==
==34301== 4 bytes in 1 blocks are still reachable in loss record 1 of 1
==34301== at 0x4C2A879: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==34301==
==34301== LEAK SUMMARY:
==34301== definitely lost: 0 bytes in 0 blocks
==34301== indirectly lost: 0 bytes in 0 blocks
==34301== possibly lost: 0 bytes in 0 blocks
==34301== still reachable: 4 bytes in 1 blocks
==34301== suppressed: 0 bytes in 0 blocks
这意味着您还应该注意in use at exit
类别。
似乎valgrind没有漏掉它,只是把它放在另一个类别中,可能是因为它们认为只有当您无法通过任何方式追踪到该地址并释放它时才会丢失某些东西,但是这个变量永远不会丢失。
int *x = new int;
int main()
{
x = new int;
return 0;
}
被检测为泄漏,因为您确实失去了对您分配的内存的跟踪。
EDIT:如Mem-check手册所述:
"仍可及"。这包括情况1和2(对于BBB块)以上。块的开始指针或开始指针链是发现。由于该块仍然是指向的,程序员可以在至少在原则上,在程序退出之前释放它。"还可到达的块是很常见的,可以说不是问题。因此,通过默认情况下,Memcheck不会单独报告这些块。
所以正如他们在检测到它之前注意到的,他们只是认为它不那么令人兴奋
Valgrind不是检测所有可能的内存泄漏存在或不存在的完美工具,而是一个可以检测某些内存泄漏的有用工具。这意味着不能使用valgrind输出来确定特定代码段是否包含任何泄漏。
你的new
s都没有对应的delete
s,从这个意义上说,它们都是泄漏的。
很可能valgrind认为number0
内存没有泄漏,因为它指向的内存在程序执行结束时是可访问的。与此相反,number1
超出了作用域,因此它指向的内存在程序执行结束时不可达,因此valgrind认为它被泄露了。
我在使用valgrind 3.8.1/g++ 4.8.1时发现了两个漏洞:
$ g++ -o foo -g foo.cc
$ valgrind ./foo
...
==7789== HEAP SUMMARY:
==7789== in use at exit: 8 bytes in 2 blocks
==7789== total heap usage: 2 allocs, 0 frees, 8 bytes allocated
==7789==
==7789== LEAK SUMMARY:
==7789== definitely lost: 4 bytes in 1 blocks
==7789== indirectly lost: 0 bytes in 0 blocks
==7789== possibly lost: 0 bytes in 0 blocks
==7789== still reachable: 4 bytes in 1 blocks
==7789== suppressed: 0 bytes in 0 blocks
在我的测试中,"绝对丢失"字节在main
中。
This
int *number0 = new int;
不是内存泄漏,因为它在执行结束时被回收。
这个配置是一个[潜在的]内存泄漏,因为
int main()
{
int *number1 = new int;
}
代码的其他部分可以调用
main () ;
,可以重复调用