2014-09-23 29 views
6

有人能夠闡明爲什麼Valgrind將此程序歸類爲「絕對丟失:2個字節的1塊」內存泄漏?我瞭解評論線可以解決問題,但我不瞭解分類。根據Valgrind文檔,內存泄漏應該被分類爲「間接可達」。我也很好奇,爲什麼這甚至被認爲是內存泄漏,並會讚賞解釋。即使程序在main函數的末尾終止,是否手動釋放所有內容是一種好的做法?在C程序中肯定會失去內存泄漏

#include <stdlib.h> 

struct wrapper { 
    char *data; 
}; 

char *strdup(const char *); 

struct wrapper *walloc(struct wrapper *root) 
{ 
    if (root == NULL){ 
    root = (struct wrapper *) malloc(sizeof(struct wrapper)); 
    root->data = strdup("H"); 
    } 

    return root; 
} 

int main(){ 
    struct wrapper *root; 

    root = NULL; 
    root = walloc(root); 

    //free(root->data); 

    return 0; 
} 

這裏是Valgrind的輸出:

$ valgrind --leak-check=full ./leak 
==26489== Memcheck, a memory error detector 
==26489== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. 
==26489== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info 
==26489== Command: ./leak 
==26489== 
==26489== 
==26489== HEAP SUMMARY: 
==26489==  in use at exit: 2 bytes in 1 blocks 
==26489== total heap usage: 2 allocs, 1 frees, 1,790 bytes allocated 
==26489== 
==26489== 2 bytes in 1 blocks are definitely lost in loss record 1 of 1 
==26489== at 0x4C29F90: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==26489== by 0x4EB79C9: strdup (in /usr/lib/libc-2.20.so) 
==26489== by 0x400542: walloc (leak.c:13) 
==26489== by 0x400542: main (leak.c:23) 
==26489== 
==26489== LEAK SUMMARY: 
==26489== definitely lost: 2 bytes in 1 blocks 
==26489== indirectly lost: 0 bytes in 0 blocks 
==26489==  possibly lost: 0 bytes in 0 blocks 
==26489== still reachable: 0 bytes in 0 blocks 
==26489==   suppressed: 0 bytes in 0 blocks 
==26489== 
==26489== For counts of detected and suppressed errors, rerun with: -v 
==26489== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0) 
+2

「它是很好的做法,即使該程序在主函數結束時終止手動自由的一切嗎?」是的,即使操作系統釋放內存,也要這樣做。 'free()'可以暴露程序中的錯誤,否則很難找到它們。在完成分配代碼後直接執行解除分配是一種好習慣。 – Lundin 2014-09-23 06:35:24

+2

我沒看到這個。我看到8個字節肯定丟失('root'),2個字節間接丟失('root-> data')。你能發佈valgrind的完整輸出嗎? – 2014-09-23 06:38:07

+0

你應該'#include ',因爲編譯器可以用'strdup'(和[GCC](http://gcc.gnu.org/)有時候做)「神奇」的東西 – 2014-09-23 06:42:15

回答

2

感謝@sharth指引我在正確的方向。 Valgrind實際上正確地檢測到了直接損失,但是由於-O3編譯完全刪除了root,所以令人困惑。編譯沒有-O3顯示8字節的合適的直接損失和2字節的間接損失。

此外,感謝@SylvainL和@Lundin的最佳實踐評論。

FYI:校正Valgrind的輸出是這樣的:

==30492== Memcheck, a memory error detector 
==30492== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. 
==30492== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info 
==30492== Command: ./leak 
==30492== 
==30492== 
==30492== HEAP SUMMARY: 
==30492==  in use at exit: 10 bytes in 2 blocks 
==30492== total heap usage: 3 allocs, 1 frees, 1,830 bytes allocated 
==30492== 
==30492== 10 (8 direct, 2 indirect) bytes in 1 blocks are definitely lost in loss record 2 of 2 
==30492== at 0x4C29F90: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==30492== by 0x400687: walloc (leak.c:12) 
==30492== by 0x4006C6: main (leak.c:23) 
==30492== 
==30492== LEAK SUMMARY: 
==30492== definitely lost: 8 bytes in 1 blocks 
==30492== indirectly lost: 2 bytes in 1 blocks 
==30492==  possibly lost: 0 bytes in 0 blocks 
==30492== still reachable: 0 bytes in 0 blocks 
==30492==   suppressed: 0 bytes in 0 blocks 
==30492== 
==30492== For counts of detected and suppressed errors, rerun with: -v 
==30492== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0) 
3

的strdup(使用malloc),因此你需要的時候它不再像使用你自己的人來釋放此內存堆上分配內存直接調用malloc。

即使程序完成,您也必須這樣做,因爲這是檢測內存泄漏的唯一方法。當然,當程序完成時,檢查任何內存泄漏的概念可能看起來有點矯枉過正,因爲所有分配的內存然後由操作系統自動釋放,但不要忘記您的小程序在這裏是個例外。通常,大多數程序在運行時會佔用非常大的內存,並且可能會耗盡內存,或者如果內部存在多個內存泄漏,則運行速度會更慢。

即使是一個小程序也應該寫得很好;否則以後你不可能再編寫任何大型程序,因爲你的不良習慣會導致大量的編碼錯誤。

+0

感謝您的回覆。爲什麼Valgrind在字符串嵌套在結構中時將其報告爲直接泄漏?另外,爲什麼Valgrind不會抱怨釋放分配給'root'的內存? – 2014-09-23 17:06:48

+0

對不起,我不使用Valgrind,因此我不知道它使用的各種定義。也許分配給root用戶的內存就是它所稱的「損失記錄」,但您應該查看文檔或者在專門針對Valgrind的論壇中提問,或者在此處專門寫關於Valgrind的另一個問題。 – SylvainL 2014-09-23 17:26:40