【问题标题】:Unzip buffer with large data length is crashing具有大数据长度的解压缩缓冲区正在崩溃
【发布时间】:2015-08-13 14:42:43
【问题描述】:

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

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);

经过一两次迭代。谁能帮帮我?

【问题讨论】:

  • 也许你应该确切地告诉它是如何崩溃的。顺便说一句 - 这可能是堆栈溢出问题吗? char c[dataLength]; 约为。 600.000 个字符。
  • 解压不是解密。

标签: c++ buffer zlib inflate compression


【解决方案1】:

如果您的代码通常可以正常工作,但对于大型数据集却失败了,那么这可能是由于@StillLearning 在他的评论中指出的堆栈溢出。

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

char c[dataLength];

加上代码中的其他分配(最后是inflate() 函数),这可能已经太多了。为了克服这个问题,你应该动态分配内存:

char* c = new char[dataLength];

如果你这样,那么请不要忘记在你的unzipBuffer()函数结束时释放分配的内存:

delete[] c;

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

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


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

【讨论】:

  • 感谢您的帮助,但问题仍然存在。感谢您的建议,我会继续动态分配内存。
  • 不客气!另请查看@MarkAdler 的答案。他提出了一个让我怀疑的观点。我没有包括它,因为我不完全知道 zlib 是如何工作的。只需尝试 3 次而不是 1.5 次。如果它有效,那么您需要动态重新分配缓冲区以扩大它。
  • @Grace:我在回答中添加了一些关于“重新分配”问题的解释。
  • 感谢您的大力帮助,我将更改代码以满足您的解释,并在完成后通知您
  • 效果很好。谢谢:D
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-02
    • 1970-01-01
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    • 2016-08-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多