2014-07-14 61 views
0

我目前在C++ 11程序中使用libzip来提取压缩文件的内容并将它们存储到数据结构中,该数据结构也将保存与该文件相关的元数据。libzip无法关闭文件

我使用的是电流法爆炸zip文件,并得到每个文件在其中的内容:

void explodeArchive(const string& path, vector<ZipFileModel>& files) { 
    int error = 0; 
    zip *zip = zip_open(path.c_str(), 0, &error); 
    if (zip == nullptr) { 
     throw logic_error("Could not extract content of file " + path); 
    } 
    const zip_int64_t n_entries = zip_get_num_entries(zip, ZIP_FL_UNCHANGED); 
    for (zip_int64_t i = 0; i < n_entries; i++) { 
     const char *file_name = zip_get_name(zip, i, ZIP_FL_ENC_GUESS); 
     struct zip_stat st; 
     zip_stat_init(&st); 
     zip_stat(zip, file_name, ZIP_FL_NOCASE, &st); 
     char *content = new char[st.size]; 
     std::cerr << file_name << std::endl; 
     zip_file *file = zip_fopen(zip, file_name, ZIP_FL_NOCASE); 
     const zip_int64_t did_read = zip_fread(file, content, st.size); 
     if (did_read <= 0) { 
     continue; 
     } 
     if (strlen(content) < st.size) { 
     LOG(WARNING)<< "File " << file_name << " is truncated."; 
     } 
     if (strlen(content) > st.size) { 
     content[st.size] = '\0'; 
     } 

     ZipFileModel model; 
     model.name = string(file_name); 
     model.content = string(content); 
     model.order = -1; 
     files.push_back(model); 

     zip_fclose(file); 
     delete[] content; 
    } 
    zip_close(zip); 
    } 

我的问题是,我得到随机分段错误使用gdb指向zip_fclose(file);

Program received signal SIGSEGV, Segmentation fault. 
0x00000001001ef8a0 in zip_source_close (src=0x105001b00) at /Users/xxx/Projects/xxx/xxx/src/libzip/zip_source_close.c:48 
48  (void)src->cb.l(src->src, src->ud, NULL, 0, ZIP_SOURCE_CLOSE); 

什么是最好的方式来调试呢?正如我所说的那样间歇发生,所以很难确定确切的原因。

+1

我不认为'strlen'被正确的使用存在。我可能是错的。然而,'content [st.size] ='\ 0';'是绝对错误的,因为数组只有'st.size'元素。 –

+3

我最好的建议是不要调试这个,而是使用不太容易出现这种错误的结构重写它。特别是'std :: vector '而不是'new char []',但是如果打开失败,则抛出'zip_file *'的RAII封装也会有所帮助。即使这不能修复这些错误,也可以更容易地进行调试。 –

+0

谢谢,我正在研究它,但我不认为这是可能的。 – ruipacheco

回答

1

当没有东西需要读取时,您没有关闭zip_file。

首先,打开里面的文件:

zip_file *file = zip_fopen(zip, file_name, ZIP_FL_NOCASE); 

然后尝试读的东西:

const zip_int64_t did_read = zip_fread(file, content, st.size); 

,如果有什么看你继续和该文件是永远不会关闭。

if (did_read <= 0) { 
    continue; 
    } 

所以,只需添加:

if (did_read <= 0) { 
    zip_fclose(file); 
    continue; 
}