2012-07-25 100 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流並且未壓縮數據的校驗值與流尾部的校驗值匹配。