2010-11-16 39 views
4

當運行Valgrind的的memcheck工具,我經常收到幾十萬(或更多,因爲Valgrind的在100K切斷)的小無效讀語句,如:我是否需要擔心Valgrind在我的應用程序範圍之外報告錯誤?

==32027== Invalid read of size 1 
==32027== at 0x3AB426E26A: _IO_default_xsputn (in /lib64/libc-2.5.so) 
==32027== by 0x3AB426CF70: [email protected]@GLIBC_2.2.5 (in /lib64/libc-2.5.so) 
==32027== by 0x3AB42621FA: fwrite (in /lib64/libc-2.5.so) 
==32027== by 0x4018CA: STARCH_gzip_deflate (in /home/areynolds/trunk/utility/applications/bed/starch/bin/starch) 
==32027== by 0x401F48: compressFileWithGzip (in /home/areynolds/trunk/utility/applications/bed/starch/bin/starch) 
==32027== by 0x4028B5: transformInput (in /home/areynolds/trunk/utility/applications/bed/starch/bin/starch) 
==32027== by 0x402F12: main (in /home/areynolds/trunk/utility/applications/bed/starch/bin/starch) 
==32027== Address 0x7febb9b3c is on thread 1's stack 

這些陳述是指函數調用外我的申請(「starch」)和似乎是libc的一部分。這是我需要關心的嗎?

編輯

如果我修改fwrite調用刪除一個字節,然後我的gzip流被破壞。這裏是原代碼:

int STARCH_gzip_deflate(FILE *source, FILE *dest, int level) {                                                    

    int ret, flush;                                                               
    unsigned have;                                                               
    z_stream strm;                                                               
    unsigned char in[STARCH_Z_CHUNK];                                                          
    unsigned char out[STARCH_Z_CHUNK];                                                          

    /* initialize deflate state */                                                            
    strm.zalloc = Z_NULL;                                                             
    strm.zfree = Z_NULL;                                                              
    strm.opaque = Z_NULL;                                                             

    /* deflateInit2 allows creation of archive with gzip header, i.e. a gzip file */                                               
    /* cf. http://www.zlib.net/manual.html */                                                        
    ret = deflateInit2(&strm, level, Z_DEFLATED, (15+16), 8, Z_DEFAULT_STRATEGY);                                               
    if (ret != Z_OK)                                                               
     return ret;                                                               

    /* compress until end of file */                                                           
    do {                                                                  
     strm.avail_in = fread(in, 1, STARCH_Z_CHUNK, source);                                                    
     if (ferror(source)) {                                                            
      (void)deflateEnd(&strm);                                                           
      return Z_ERRNO;                                                             
     }                                                                 
     flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;                                                      
     strm.next_in = in;                                                             

     do {                                                                 
      strm.avail_out = STARCH_Z_CHUNK;                                                         
      strm.next_out = out;                                                            
      ret = deflate(&strm, flush);                                                          
      assert(ret != Z_STREAM_ERROR);                                                         
      have = STARCH_Z_CHUNK - strm.avail_out;  

      /* invalid read happens here */                                                      
      if (fwrite(out, 1, have, dest) != have || ferror(dest)) {                                                  
       (void)deflateEnd(&strm);                                                          
       return Z_ERRNO;                                                            
      }                                                                
     } while (strm.avail_out == 0);                                                          
     assert(strm.avail_in == 0);                                                           

    } while (flush != Z_FINISH);                                                            
    assert(ret == Z_STREAM_END);                                                            

    /* clean up and return */                                                            
    (void)deflateEnd(&strm);                                                             
    return Z_OK;                                                                
} 

EDIT 2

我想我看到的問題。我有in[STARCH_Z_CHUNK]而不是in[STARCH_Z_CHUNK + 1](同樣對於out[])。如果我通過-1同時調整freadfwrite聲明,我似乎並沒有得到那些Invalid read of size 1陳述,儘管我仍然看到了大量的Invalid read of size 48所特有的zlib

==32624== Invalid read of size 4 
==32624== at 0x3AB5206455: deflateInit2_ (in /usr/lib64/libz.so.1.2.3) 
==32624== by 0x40180E: STARCH_gzip_deflate (in /home/areynolds/trunk/utility/applications/bed/starch/bin/starch) 
==32624== by 0x401F48: compressFileWithGzip (in /home/areynolds/trunk/utility/applications/bed/starch/bin/starch) 
==32624== by 0x402C03: transformInput (in /home/areynolds/trunk/utility/applications/bed/starch/bin/starch) 
==32624== by 0x402F12: main (in /home/areynolds/trunk/utility/applications/bed/starch/bin/starch) 
==32624== Address 0x7feafde38 is on thread 1's stack 

編輯3

我正在用-g重新編譯,如前所述,它將行號與錯誤關聯起來。

但我只是在做argv[]strncpy一個簡單的變量,例如:

strncpy(uniqTag, argv[2], strlen(argv[2]) + 1); 

這應在空值終止字符串argv[2]複製到uniqTag,但仍valgrind標誌着這是一個錯誤。

EDIT 4

這裏的錯誤消息:

==3682== Invalid read of size 1 
==3682== at 0x4A081C1: strncpy (mc_replace_strmem.c:329) 
==3682== by 0x4022F1: parseCommandLineInputs (starch.c:589) 
==3682== by 0x402F20: main (starch.c:46) 
==3682== Address 0x7fedffe11 is on thread 1's stac 

下面是兩個相關線; Valgrind是說,第二行是無效讀:

uniqTag = (char *)malloc(strlen(argv[2]) + 1); 
strncpy(uniqTag, argv[2], strlen(argv[2]) + 1); 

因爲strlen(argv[2]) + 1 > strlen(argv[2]),這將導致一個空值終止uniqTag

+0

其實它可能是你的緩衝區,需要得到大一點,而不是fwrite(),需要剋制自己... – thkala 2010-11-16 22:09:27

+0

嘗試增加緩衝區的大小1,看看會發生什麼 – thkala 2010-11-16 22:19:18

+1

順便說一句,你是用調試符號編譯你的代碼?如果在編譯器選項中使用-g(假設你使用gcc),valgrind會發出更精確和有用的消息。 – thkala 2010-11-16 22:21:01

回答

5

在這種情況下,我會說你這樣做。 libc函數參數來自你的程序。我冒險猜測並說你的代碼中有一個錯誤導致fwrite讀取源緩衝區末尾的一個字節。

編輯:

順便說,這樣的小誤差可以經常保持看不見(即您的代碼不會崩潰),因爲編譯器和內存分配程序通常會分配特定大小的內存塊,並將它們對齊到文字邊緣。這意味着多次有一個小區域通過請求的緩衝區末端,您可以訪問而不觸發內存保護代碼。當然,如果你改變編譯器,libc,平臺或位(例如從64位到32位),你的代碼可能會中斷。

Valgrind對libc中的預期錯誤有抑制列表,通常可以在/usr/lib64/valgrind/default.supp或/usr/lib/valgrind/default.supp處找到它們。 valgrind在libc中檢測到的問題有很多,其中很多是爲了優化代碼而故意的,但是由於99%的情況下這是導致問題的測試代碼。

EDIT2:

請記住,最喜歡的調試工具,對這些問題Valgrind的將輸出無限更多有用的信息,如果你與調試符號編譯代碼檢測。它將能夠向您指出與問題相關的特定代碼行 - 即使它們通常不是實際問題所在。如果您使用GCC,只需在其選項中添加-g以使用調試符號編譯您的代碼。但是,在產品發佈中,請記住刪除該標誌!

+0

對於_off_ __ __一個建議+1。我沒有想到這一點。 – nategoose 2010-11-16 21:49:35

1

你應該追蹤調用堆棧,直到找到你的代碼並尋找錯誤的起源。在這種情況下,STARCH_gzip_deflate看起來叫fwrite有一些壞的東西(可能是壞的FILE *或你試圖寫出來的緩衝區),這會導致valgrind向你咆哮。

雖然這可能不是實際的錯誤,也可能不是您的錯誤。但它可能是。

相關問題