0

我从以下函数中得到内存泄漏:

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,看看他们是否隐藏了“陷阱”,他们在某处调用 new[],但在 cplusplus.com 上的文档中没有找到任何内容。我已经尝试了 new char[]/delete[]、malloc/free 和堆栈分配变量(上图)的所有不同组合,但我每次都收到相同的 valgrind 消息。有任何想法吗?谢谢。

4

3 回答 3

7

你打电话

  • char readbuf[len + 1];

    然后稍后

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

那不会溢出数组吗?

于 2013-05-29T22:12:38.813 回答
0

I found out the problem actually had to do with the Makefile I was using. Thanks for the insight on my slip-up with the char[] bounds though!

于 2013-05-30T21:14:29.023 回答
0

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

但是很有可能您的编译器将此功能实现为非标准扩展,并且它通过对new[]. 这就是为什么您会收到指向 的错误消息new[],即使您没有new[]明确使用。

当然,编译器有责任在这些数组结束其生命周期时释放它们。我怀疑编译器做了所有它必须做的事情,但是valgrind编译器的行为让编译器感到困惑,这使得它得出结论是内存泄漏。

此外,正如其他人已经指出的那样,您正在越界访问您的数组,这也可能导致运行时出现任何问题,包括来自valgrind.

于 2013-05-30T17:06:56.713 回答