2012-07-25 96 views
1

当我尝试解压大于2048的数据时,zlib解压缩调用返回Z_OK。因此,为了澄清如果我解压缩大小为2980的数据,它将解压缩到2048(两个循环),然后返回Z_OK。 我错过了什么?zlib在缓冲区扩展上停止

字节是一个矢量< unsigned char>;

Bytes uncompressIt(const Bytes& data) 
    { 
     size_t buffer_length = 1024; 

     Byte* buffer = nullptr; 

     int status = 0; 

     do 
     { 
      buffer = (Byte*) calloc(buffer_length + 1, sizeof(Byte)); 

      int status = uncompress(buffer, &buffer_length, &data[ 0 ], data.size()); 

      if (status == Z_OK) 
      { 
       break; 
      } 
      else if (status == Z_MEM_ERROR) 
      { 
       throw runtime_error("GZip decompress ran out of memory."); 
      } 
      else if (status == Z_DATA_ERROR) 
      { 
       throw runtime_error("GZip decompress input data was corrupted or incomplete."); 
      } 
      else //if (status == Z_BUF_ERROR) 
      { 
       free(buffer); 

       buffer_length *= 2; 
      } 
     } while (status == Z_BUF_ERROR); //then the output buffer wasn't large enough 

     Bytes result; 

     for(size_t index = 0; index != buffer_length; index++) 
     { 
      result.push_back(buffer[ index ]); 
     } 

     return result; 
    } 

编辑:

感谢@迈克尔用于捕获的realloc。我一直在关注实现并错过了它;发布之前仍然没有任何借口。

+0

实际问题是什么?它不解压大于2048字节或小于? – slugonamission 2012-07-25 20:41:36

+0

如果您将buffer_length加倍并跳回到calloc(),则realloc()是不必要的。如果在错误情况下通过解压缩来更改buffer_length,该怎么办?加倍是正确的事情吗?也许你应该使用不同的值来捕获未压缩数据的长度来保存buffer_length。 – brandx 2012-07-25 20:43:08

+0

@brandx感谢解压缓冲区长度改变的建议,但我已经检查过,而不是这种情况。 – Corvusoft 2012-07-25 20:58:12

回答

1

我明白了。

int status 

定义在循环内部和外部。这里的课是从不喝酒&发展。

0

从zlib手册中:“在没有足够空间的情况下,uncompress()将使用未压缩的数据填充输出缓冲区直到那个点。”

也就是说,最多1024字节已经被解压,那么你得到了Z_BUF_ERROR,并且缓冲区大小增加了两倍,给你2048字节的空间,并且一旦你第二次解压缩,总共可以达到3072未压缩数据的字节。

另外,它看起来像你不必要地做calloc之后realloc当你得到Z_BUF_ERROR

+0

我已经阅读了手册,并没有从阅读您的评论中采取任何新的行动。我相信你是在暗示uncompress调用会记住之前的调用...是的?不过,我没有读任何建议。 – Corvusoft 2012-07-25 21:01:57

0

我发现没有什么明显的是你的代码有问题。您可能会错误预测未压缩数据的长度。 uncompress()将只返回Z_OK,如果它解压了一个完整的zlib流并且未压缩数据的校验值与流尾部的校验值匹配。