内存泄漏通过new []而没有调用new

时间:2013-05-29 22:07:03

标签: c++ memory-leaks new-operator valgrind fread

我从以下函数中获取内存泄漏:

int ReadWrite(int socket, char *readfile) {
  FILE *rf = NULL;
  rf = fopen(readfile, "rb");
  fseek(rf, 0, SEEK_END);
  int len = ftell(rf);
  rewind(rf);

  char readbuf[len + 1];

  int res = fread(readbuf, len, 1, rf);
  readbuf[len + 1] = '\0';
  fclose(rf);
  while (1) {
    int wres = write(socket, readbuf, res);
    if (wres == 0) {
      cerr << "socket closed prematurely" << endl;
      close(socket);
      return EXIT_FAILURE;
    }
    if (res == -1) {
      if (errno == EINTR)
        continue;
      cerr << "socket write failure: " << strerror(errno) << endl;
      close(socket);
      return EXIT_FAILURE;
    }
    break;
  }
  return EXIT_SUCCESS;
}

Valgrind告诉我,我通过此操作泄漏了readfile中的字节数(实际文件,而不是readfile的名称):

Address 0x4c3b67e is 0 bytes after a block of size 14 alloc'd
at 0x4A07C84: operator new[](unsigned long) (vg_replace_malloc.c:363)

令我困惑的是我在代码中没有使用new []。我检查了fopen,ftell和fread,看看他们是否隐藏了“gotcha's”,他们在某处调用new [],但在cplusplus.com的文档中没有找到任何内容。我已经尝试了新的char [] / delete [],malloc / free和stack-allocated变量(上面)的所有不同组合,但每次都得到相同的valgrind消息。有任何想法吗?感谢。

3 个答案:

答案 0 :(得分:7)

你打电话

  • char readbuf[len + 1];

    然后再

  • readbuf[len + 1] = '\0';

不会溢出数组吗?

答案 1 :(得分:0)

嗯,您声明您的readbuf数组具有非常数大小(即具有运行时大小)。这在C ++中是正式非法的。这种特性存在于C99中,但不存在于C ++中。您的代码甚至不会在迂腐的C ++编译器中编译。你的问题被标记为[C ++]。

但很可能您的编译器将此功能实现为非标准扩展,并且它通过对new[]的隐式调用来创建此类数组。这就是您收到引用new[]的错误消息的原因,即使您没有明确使用new[]

当然,编译器有责任在这些数组的生命周期结束时释放它们。我怀疑编译器完成了所有必须做的事情,但是valgrind被编译器操作中的某些东西搞糊涂了,这使得它得出结论是内存泄漏。

此外,正如其他人已经指出的那样,你对数组进行了界限访问,这也可能导致运行时出现任何问题,包括来自valgrind的奇怪报告。

答案 2 :(得分:0)

我发现问题实际上与我正在使用的Makefile有关。感谢您对char []界限的了解!