2012-09-18 25 views
7

我一直在使用libzip處理zip文件,並且在rodrigo對this question的答案中找到了示例。下面是他的代碼,爲快速參考:Libzip示例包含使用Valgrind進行檢查時的未初始化值

#include <zip.h> 

int main() 
{ 
    //Open the ZIP archive 
    int err = 0; 
    zip *z = zip_open("foo.zip", 0, &err); 

    //Search for the file of given name 
    const char *name = "file.txt"; 
    struct zip_stat st; 
    zip_stat_init(&st); 
    zip_stat(z, name, 0, &st); 

    //Alloc memory for its uncompressed contents 
    char *contents = new char[st.size]; 

    //Read the compressed file 
    zip_file *f = zip_fopen(z, "file.txt", 0); 
    zip_fread(f, contents, st.size); 
    zip_fclose(f); 

    //And close the archive 
    zip_close(z); 
} 

我跟蹤我隨後從Valgrind的一回到這個代碼 - 它抱怨的未初始化值的錯誤打開壓縮文件「file.txt」使用「zip_fopen()`當。

==29256== Conditional jump or move depends on uninitialised value(s) 
==29256== at 0x5B4B290: inflateReset2 (in /usr/lib/libz.so.1.2.3.4) 
==29256== by 0x5B4B37F: inflateInit2_ (in /usr/lib/libz.so.1.2.3.4) 
==29256== by 0x4E2EB8C: zip_fopen_index (in /usr/lib/libzip.so.1.0.0) 
==29256== by 0x400C32: main (main.cpp:24) 
==29256== Uninitialised value was created by a heap allocation 
==29256== at 0x4C244E8: malloc (vg_replace_malloc.c:236) 
==29256== by 0x5B4B35B: inflateInit2_ (in /usr/lib/libz.so.1.2.3.4) 
==29256== by 0x4E2EB8C: zip_fopen_index (in /usr/lib/libzip.so.1.0.0) 
==29256== by 0x400C32: main (main.cpp:24) 
==29256== 
==29256== 
==29256== HEAP SUMMARY: 
==29256==  in use at exit: 71 bytes in 1 blocks 
==29256== total heap usage: 26 allocs, 25 frees, 85,851 bytes allocated 
==29256== 
==29256== 71 bytes in 1 blocks are definitely lost in loss record 1 of 1 
==29256== at 0x4C24A72: operator new[](unsigned long) (vg_replace_malloc.c:305) 
==29256== by 0x400BEE: main (main.cpp:19) 

我看不到未初始化值來自此代碼的位置。任何人都可以追溯這個問題,還是錯誤在於libzip本身?我應該切換到另一個zip庫嗎?例如Minizip?

編輯:71個字節是file.txt的內容,它被讀取到delete[] contents;的末尾會標記出來。

(我會留在原來的答案提請注意這一問題的評論,但我沒有必要的代表。)

+0

堆棧跟蹤有點奇怪,你調用zip_fopen,但它說你在zip_fopen_index。看不到有任何'#define'用另一個定義,所以不得不詢問它是否是正確的堆棧跟蹤。 –

+0

我同意!我在zip.h中看不到這樣的東西,這是在這裏問的另一個原因。絕對是正確的道路,但我只是再次運行檢查。我很想看看其他人是否可以重現這一點。 –

+0

您必須查看'inflateReset2()'的源代碼才能嘗試確定在初始化之前哪個變量正在用作條件。我相信,源代碼也包含'zip_fopen_index()'問題的答案。 – twalberg

回答

6

你讓我看看:)

是的,這是zlib中的錯誤(由libzip使用),因爲在同一次調用中,內存的分配和使用都在inflateInit2_之內。你的代碼甚至沒有機會獲得該內存。

我可以重複使用zlib 1.2.3的問題,但它不再顯示在1.2.7中。我沒有1.2.3的代碼,但是如果你正在查看它,我會檢查state的初始化以及它在inflateReset2中的使用方式。

編輯:追蹤了這個問題,我下載了Ubuntu的zlib源代碼包(1.2.3.4),並且有問題的一行是;

if (state->wbits != windowBits && state->window != Z_NULL) { 

wbits在此之前未被初始化,並且會導致警告。奇怪的是,原來的zlib 1.2.3或1.2.4都沒有這個問題,它似乎是Ubuntu獨有的。 1.2.3甚至沒有函數inflateReset2,並且1.2.4沒錯;

if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) { 
因爲 window

預先初始化爲Z_NULL,未初始化wbits讀不會發生。