重新分配期间Valgrind内存泄漏

时间:2018-09-24 12:45:05

标签: c memory-leaks

我不确定为什么Valgrind会报告内存泄漏?

.c文件中的伪代码:

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>

 char* str_alloc(char *str) {
   char* dup = (char*) malloc((strlen(str) + 1) * sizeof(char));
   strcpy((char*) dup, (char*) str);
   return dup;
 }

 void function_c(char **name) {
   int len = 10;
   (void) realloc(*name, 100);
 }

 void function_b(char **name) {
   (void) function_c(name);
 }

 void function_a(char **name) {
   (void) function_b(name);
 }

 int main() {
   char* name = str_alloc("");
   function_a(&name);
   // Do something with name
   free(name);
 }

我忽略了realloc的值,因为我确定realloc将始终位于同一指针上。从我自己的内存池分配/重新分配,这是非常大的。

当然,我不能在这里编写内存池的代码。

那么,在什么情况下我会因为Valgrind泄漏而来?我想到的几个案例:

  • 如果重新分配发生在较小的内存上。保证realloc会照顾好它。
  • 如果realloc失败,则认为是内存泄漏。我明白这一点。

还有其他情况吗?

2 个答案:

答案 0 :(得分:3)

存在内存泄漏,因为您丢失了realloc分配的内存。

realloc的语法如下。

void *realloc(void *ptr, size_t size); 

注意:不能保证realloc返回的指针与传递给realloc的旧指针相同,并且不应依赖于该指针。

甚至编译器也会警告您同样的情况。

  

警告:忽略使用属性声明的“ realloc”的返回值   warn_unused_result [-Wunused-result]

(void) realloc(*name, 100);
^

因此,您需要按以下方式修改function_c函数。

 void function_c(char **name) 
 {
     char *newPtr = NULL;
     newPtr  =  realloc(*name, 100);
     *name = newPtr;
 }

答案 1 :(得分:2)

  

我忽略了realloc的值,因为我确定realloc将始终位于同一指针上。从我自己的内存池分配/重新分配,这是非常大的。

在使用标准malloc / realloc / free接口的代码中,您根本无法做出此假设,即使您认为自己提供了实现并且知道在受控条件下的行为,也是如此。未来从事代码工作的人(包括您自己,从您忘记了该项目的细节之后的几年以后)将假设您的代码如何使用标准接口并没有什么特别之处,他们可以将代码移至完全不同的C实现中而无需引入您的特殊malloc库。

此外,C库有权拒绝让您替换这些函数,这是导致您直接遇到的问题的原因:valgrind强制用malloc / realloc / free的 own 实现替换您拥有的任何东西,从不从realloc返回相同指针的实现。这是有意为的,以捕获此类错误。

如果要实现一个保证“调整分配大小不会移动分配”之类的内存池,则需要为所有函数赋予新名称(例如pool_alloc,{{1} },pool_resize