为什么Valgrind在realloc()之后报告无效的free()?

时间:2012-05-06 22:22:43

标签: c free valgrind realloc

当我在以下(示例)代码上运行valgrind时,它报告“无效的free()/ delete / delete []”和Invalids读取。我真的不明白为什么。有人可以解释一下吗?

编辑:感谢您的回复,现在已经很明显了。

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

void vl_dec(char* a) {
  char* str = a;
  while (*(str+1) != '\0') str++;
  while(*str == '0') {
    *str = '9';
    str--;
  }
  (*str)--;

  if (*a == '0') {
    memmove(a, a+1, strlen(a));
    a = (char*)realloc(a, (strlen(a)+1)*sizeof(char));
    if (a == NULL) {
      fprintf(stderr, "Cannot allocate memory\n");
      exit(1);
    }
  }
}

int main(int argc, char* argv[]) {
  char* a = (char*)malloc(6*sizeof(char));
  if (a == NULL) {
    fprintf(stderr, "Cannot allocate memory\n");
    exit(1);
  }
  strcpy(a, "10000");
  vl_dec(a);
  printf("%s\n", a);
  free(a);
  return 0;
}

3 个答案:

答案 0 :(得分:3)

在您的函数main中,您按值a传递给vl_dec,因此它永远不会更新 - realloc的结果只存储在局部变量中vl_dec返回时丢失了。相反,传递其地址:

void vl_dec(char ** a) { *a = realloc(...); }

int main()
{
    char * a = malloc(...);
    vl_dec(&a);
    free(a);
}

答案 1 :(得分:1)

您不能假设a返回的realloc的新值与旧值相同。实际上,您必须在每次使用它的地方更新指针。我怀疑您知道这一点,因为您在realloc内正确保存了vl_dec的返回值,但是您忘记了需要从a返回vl_dec的新值(或使用char**作为vl_dec的参数来更新它。)

答案 2 :(得分:0)

因为您按指令将指针传递给vl_dec,而不是通过引用传递。

如果realloc你的主函数vl_dec内的指针仍然会看到在main中声明的原始指针。在指针无效的realloc之后,valgrind会抱怨。

解决此问题的一种简单方法是重写vl_dec并让它返回指针。这样你就可以打电话:

   a = vl_dec(a);

主要问题解决了。