为什么Valgrind不能检测到由realloc引起的可能内存泄漏?

3

我无法理解为什么valgrind(版本3.14)不能检测到此程序中可能存在的内存泄漏:

#include <stdlib.h>

int main() {
  int *p = malloc(sizeof(int));
  p = realloc(p, 2 * sizeof(int));

  free(p);

  return 0;
}

C99标准(ISO/IEC 9899:1999,第314页)关于realloc的说明如下:
如果不能为新对象分配内存,则不会释放旧对象,并且其值不变。realloc函数返回指向新对象的指针(可能与指向旧对象的指针具有相同的值),或者如果无法分配新对象则返回空指针。
因此,可能出现p为NULL但先前使用malloc分配的内存单元仍然存在的情况,这不应该是可能的内存泄漏吗?
如果我使用gcc -std=c99编译程序,并使用valgrind --tool=memcheck --leak-check=full --track-origins=yes运行它,则会显示以下消息:
==313618== Memcheck, a memory error detector
==313618== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==313618== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==313618== Command: ./a.out
==313618== 
==313618== 
==313618== HEAP SUMMARY:
==313618==     in use at exit: 0 bytes in 0 blocks
==313618==   total heap usage: 2 allocs, 2 frees, 12 bytes allocated
==313618== 
==313618== All heap blocks were freed -- no leaks are possible
==313618== 
==313618== For counts of detected and suppressed errors, rerun with: -v
==313618== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

这就是为什么你应该将realloc的返回值分配给一个临时变量进行测试,然后再覆盖原指针的一个好理由。如果返回NULL,你的恢复操作可以释放原始指针,而不会丢失它。 - Weather Vane
2
关于valgrind在此上下文中所谓的“possible”的更多信息:https://dev59.com/JlnUa4cB1Zd3GeqPaXTy - user2201041
@WeatherVane 我知道这种使用 realloc 的方式是错误的,问题在于为什么 valgrind 没有检测到它。 - Andrea Ciceri
@JETM 这真的很有用,但是“possible”是一个误导性的名称,以及消息“no leaks are possible”... - Andrea Ciceri
1个回答

9

Valgrind不会分析您的代码,它只会分析您的代码执行操作。

在这次运行中,realloc没有失败,因此没有内存泄漏,因此valgrind没有任何报告:

所有堆块都已释放

这就是valgrind所知道的全部内容。

要检测代码中的问题,您需要使用静态代码分析工具。


1
是的,正如您在答案中所述,通过使用 cppcheck 静态 C/C++ 代码分析器,我们可以检测到这些问题。 - EsmaeelE
在GNU/Linux上,sudo apt install cppcheckcppcheck source.c会产生以下结果:9]: (error) Common realloc mistake: 'p' nulled but not freed upon failure - EsmaeelE
修正原始代码:`int *p = malloc(sizeof(int)); int *tmp = NULL;tmp = realloc(p, 2 * sizeof(int)); if (tmp){ p=tmp; free(p); p=NULL; }else{ printf("error\n"); free(tmp); tmp=NULL; } free(p);` - EsmaeelE
@EsmaeelE 谢谢,我尝试使用cppcheck并且它正确地警告了我。 - Andrea Ciceri

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接