2013-05-29 25 views
0

我碰到下面的函数内存泄漏:内存泄露而没有调用new

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的字节数(实际的文件,而不是读取文件的名称):

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和堆栈分配的变量(上面)的所有不同组合,但每次都得到相同的valgrind消息。有任何想法吗?谢谢。

+3

'炭的ReadBuf [LEN + 1];'是无效的C++。 –

+1

这是一个非常奇怪的代码:'char readbuf [len + 1]'。你使用什么编译器? –

+4

您应该更改'readbuf [len + 1] ='\ 0';'readbuf [len] ='\ 0';',除非您故意尝试超出readbuf。另外,你真的在​​使用C99,而不是C++吗? –

回答

0

我发现这个问题其实曾与我所用的Makefile来办。感谢您对char []边界的理解,尽管如此!

+0

你能解释一下Makefile的问题吗?谢谢。 –

+0

不幸的是我不记得Makefile导致问题的具体原因。但我记得那是因为我对Makefiles的工作原理有误解。对不起,我没有更多的为你 - 我能做的最好的是指向你的Makefiles教程(http://www.cs.umd.edu/class/fall2002/cmsc214/Tutorial/makefile.html)。希望这有助于。 –

7

你叫

  • char readbuf[len + 1];

    再后来

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

不会溢出的阵列?

+0

更不用说'char readbuf [len + 1]'是无效的C++,因为'len'不是'const'。 –

+0

@NikBougalis:这还不够标准,但(A)GCC已经允许它一段时间,并且(B)他们正在努力使其标准化。 –

+1

@MooingDuck GCC可以支持这一点,在这种情况下,gcc手册应解释如何存储器应该被释放(更新:它是由每[文档]编译器(http://gcc.gnu.org/onlinedocs自动释放/gcc/Variable-Length.html)),但今天它不是标准的,所以代码不是有效的C++。这是一个有效的“gcc-extended C++”,但这不同于“C++”。 –

0

那么,你与非固定大小声明你readbuf阵列(即与运行时的大小)。这在C++中是非正式的。这种功能存在于C99中,但不在C++中。你的代码甚至不会在迂腐的C++编译器中编译。你的问题被标记为[C++]。

但它很可能是你的编译器可以实现此功能作为一种非标准的扩展,并且它通过创建到new[]隐式调用这种阵列。这就是为什么您会收到引用new[]的错误消息,即使您未明确使用new[]也是如此。

当然,这是编译器的责任,当他们结束自己的一生要解除这种阵列。我怀疑编译器是否做了它所要做的所有事情,但valgrind被编译器操作中的某些东西所困惑,这就使得它认为它是内存泄漏。另外,正如其他人已经提到的那样,你正在越界访问你的数组,这也会导致运行时出现任何问题,包括来自valgrind的奇怪报告。