具有大数据长度的解压缩缓冲区正在崩溃

时间:2015-08-13 14:42:44

标签: c++ buffer zlib inflate compression

这是我用来解压缩缓冲区的函数。

string unzipBuffer(size_t decryptedLength, unsigned char * decryptedData)
{
    z_stream stream;
    stream.zalloc = Z_NULL;
    stream.zfree = Z_NULL;
    stream.avail_in = decryptedLength;
    stream.next_in = (Bytef *)decryptedData;
    stream.total_out = 0;
    stream.avail_out = 0;
    size_t dataLength = decryptedLength* 1.5;
    char c[dataLength];

    if (inflateInit2(&stream, 47) == Z_OK)
    {
        int status = Z_OK;
        while (status == Z_OK)
        {
            if (stream.total_out >= dataLength)
            {
                dataLength += decryptedLength * 0.5;
            }

            stream.next_out = (Bytef *)c + stream.total_out;

            stream.avail_out = (uint)(dataLength - stream.total_out);

            status = inflate (&stream, Z_SYNC_FLUSH);

        }
        if (inflateEnd(&stream) == Z_OK)
        {
            if (status == Z_STREAM_END)
            {
                dataLength = stream.total_out;
            }
        }
    }
    std::string decryptedContentStr(c, c + dataLength);
    return decryptedContentStr;
}

直到今天我才意识到它在这一行上崩溃了大数据缓冲区(例如:decryptedLength:342792):

status = inflate (&stream, Z_SYNC_FLUSH);

经过一两次迭代。有人可以帮帮我吗?

2 个答案:

答案 0 :(得分:2)

如果您的代码通常正常工作,但对于大型数据集失败,则可能是由于@StillLearning在其评论中指示的堆栈溢出。

通常(默认)堆栈大小为1 MB。当decryptedLength为342,792时,您尝试在以下行中分配514,188字节:

char c[dataLength];

与代码中的其他分配(以及最终在inflate()函数中)一起,这可能已经太多了。要解决此问题,您应该动态分配内存:

char* c = new char[dataLength];

如果是这样,那么请不要忘记在unzipBuffer()功能结束时释放已分配的内存:

delete[] c;

如果您忘记删除已分配的内存,则会出现内存泄漏。

如果这没有(完全)解决您的问题,您应该这样做,因为对于更大的数据集,由于堆栈的大小有限,您的代码肯定会中断。​​

如果您需要&#34;重新分配&#34;在while()循环中动态分配的缓冲区,请查看this Q&A。基本上,您需要使用newstd::copydelete[]的组合。但是,如果您将char数组与std::vector<char>std::vector<Bytef>进行交换,则更合适。然后,您可以使用resize()函数轻松扩大缓冲区。您可以使用vector直接访问&my_vector[0]的缓冲区,以便将其分配给stream.next_out

答案 1 :(得分:1)

c不会因为你增加datalength而变得更大。您可能会覆盖c的末尾,因为您对压缩大小的1.5倍的初始猜测是错误的,从而导致错误。

(这可能是堆栈溢出,如此处的另一个答案所示,但我认为现在8 MB堆栈分配很常见。)