2015-10-16 46 views
3

我有一個使用valgrind的問題。在我的項目中,所有結構都被#pragma pack(2)包圍以減少內存使用量。Valgrind和「#pragma pack(2)」

現在,將內存分配給結構中的指針會導致valgrind錯誤,例如, g .: 7個塊中的14個字節在丟失記錄2中絕對丟失3.

編輯:我不夠精確。當然,由於我從來沒有打過免費電話,所以存在內存泄漏。但問題是,valgrind認爲記憶力一定會丟失。情況並非如此,因爲param_info是靜態的。

那麼,爲什麼valgrind說,肯定失去了,而不是可以達到?如果我刪除了雜注指令,輸出如預期的那樣。

這是預期的嗎?如果是這樣,任何人都可以解釋爲什麼?

這裏是一個小例子,以重現該錯誤:

#include <stdlib.h> 

#pragma pack(push) 
#pragma pack(2) 

struct param_ref 
    { 
    short *p; 
    short max_p; 
    }; 

#pragma pack(pop) 

int main() 
{ 
    static struct param_ref *param_info = NULL; 
    static short    param_max = 0; 

    int i; 

    if (param_info == NULL) 
     { 
     param_max = 10; 
     param_info = malloc(sizeof (struct param_ref) * param_max); 

     for (i = 0; i < param_max; i++) 
      { 
      param_info[i].p  = malloc(sizeof (short)); 
      param_info[i].max_p = 1; 
      } 
     } 

    return 0; 
} 

而Valgrind的輸出:

[email protected]:~/val$ valgrind --leak-check=full ./a.out 
==4156== Memcheck, a memory error detector 
==4156== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. 
==4156== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info 
==4156== Command: ./a.out 
==4156== 
==4156== 
==4156== HEAP SUMMARY: 
==4156==  in use at exit: 120 bytes in 11 blocks 
==4156== total heap usage: 11 allocs, 0 frees, 120 bytes allocated 
==4156== 
==4156== 14 bytes in 7 blocks are definitely lost in loss record 2 of 3 
==4156== at 0x4C2BBA0: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==4156== by 0x4005AF: main (in /home/xxx/val/a.out) 
==4156== 
==4156== LEAK SUMMARY: 
==4156== definitely lost: 14 bytes in 7 blocks 
==4156== indirectly lost: 0 bytes in 0 blocks 
==4156==  possibly lost: 0 bytes in 0 blocks 
==4156== still reachable: 106 bytes in 4 blocks 
==4156==   suppressed: 0 bytes in 0 blocks 
==4156== Reachable blocks (those to which a pointer was found) are not shown. 
==4156== To see them, rerun with: --leak-check=full --show-leak-kinds=all 
==4156== 
==4156== For counts of detected and suppressed errors, rerun with: -v 
==4156== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0) 

EDIT2:的valgrind的輸出,而不pragma指令:

[email protected]:~/val$ valgrind --leak-check=full ./a.out 
==5374== Memcheck, a memory error detector 
==5374== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. 
==5374== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info 
==5374== Command: ./a.out 
==5374== 
==5374== 
==5374== HEAP SUMMARY: 
==5374==  in use at exit: 180 bytes in 11 blocks 
==5374== total heap usage: 11 allocs, 0 frees, 180 bytes allocated 
==5374== 
==5374== LEAK SUMMARY: 
==5374== definitely lost: 0 bytes in 0 blocks 
==5374== indirectly lost: 0 bytes in 0 blocks 
==5374==  possibly lost: 0 bytes in 0 blocks 
==5374== still reachable: 180 bytes in 11 blocks 
==5374==   suppressed: 0 bytes in 0 blocks 
==5374== Reachable blocks (those to which a pointer was found) are not shown. 
==5374== To see them, rerun with: --leak-check=full --show-leak-kinds=all 
==5374== 
==5374== For counts of detected and suppressed errors, rerun with: -v 
==5374== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) 
+1

你永遠不會調用'free' ......這是怎麼泄露的形式,無論包裝。 – Kninnug

回答

1

一些指向內存的指針沒有正確對齊,以便valgrind找到它們,因爲包裝因此是valgr ind報告他們肯定失去了。現在看來,這有一個像LeakSanitizer此別無選擇: LSAN_OPTIONS=use_unaligned=1

use_unaligned : If 0, LSan will only consider properly aligned 8-byte patterns when looking for pointers. Set to 1 to include unaligned patterns. This refers to the pointer itself, not the memory being pointed at.

$ gcc so.c -fsanitize=address -g 
$ ./a.out 

================================================================= 
==4943==ERROR: LeakSanitizer: detected memory leaks 

Direct leak of 14 byte(s) in 7 object(s) allocated from: 
    #0 0x7fe18898ba0a in malloc (/lib64/libasan.so.2+0x98a0a) 
    #1 0x4008d2 in main /home/m/so.c:28 
    #2 0x7fe18855378f in __libc_start_main (/lib64/libc.so.6+0x2078f) 

SUMMARY: AddressSanitizer: 14 byte(s) leaked in 7 allocation(s). 
$ LSAN_OPTIONS=use_unaligned=1 ./a.out 
$ 
+0

非常感謝!我應該更仔細地閱讀valgrind文檔:「如果--leak-check被適當地設置,對於每個剩餘塊,Memcheck確定塊是否可以從根集內的指針訪問。根集包括(a)所有線程的通用寄存器,以及(b)可訪問的客戶端存儲器(包括堆棧)中初始化的,對齊的指針大小的數據字。「 – RedPepper