2013-05-29 24 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的奇怪報告。