Разархивирование буфера с большой длиной данных происходит сбой

Это функция, которую я использую для распаковки буфера.

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

Решение

Если ваш код в целом работает правильно, но не подходит для больших наборов данных, то это может быть связано с переполнением стека, как указано @StillLearning в его комментарии.

Обычный (по умолчанию) размер стека составляет 1 МБ. Когда ваш decryptedLength равняется 342 792, то вы пытаетесь выделить 514 188 байт в следующей строке:

char c[dataLength];

Вместе с другими размещениями в вашем коде (и, наконец, в inflate() функция), это может быть уже слишком много. Чтобы преодолеть эту проблему, вы должны выделить память динамически:

char* c = new char[dataLength];

Если вы так, то, пожалуйста, не забудьте освободить выделенную память в конце вашего unzipBuffer() функция:

delete[] c;

Если вы забудете удалить выделенную память, то у вас будет утечка памяти.

В случае, если это не (полностью) решит вашу проблему, вы все равно должны это сделать, потому что для еще больших наборов данных ваш код наверняка сломается из-за ограниченного размера стека.


В случае, если вам нужно «перераспределить» ваш динамически выделенный буфер в вашем while() цикл, затем, пожалуйста, посмотрите на этот вопрос&. В основном вам нужно использовать комбинацию new, std::copy, а также delete[], Тем не менее, было бы более уместно, если ваш обмен char массив с std::vector<char> или даже std::vector<Bytef>, Тогда вы сможете легко увеличить свой буфер, используя resize() функция. Вы можете напрямую получить доступ к буферу vector используя &my_vector[0] чтобы присвоить его stream.next_out,

2

Другие решения

c не собирается становиться больше только потому, что вы увеличиваете datalength, Вы, вероятно, перезаписываете после конца c потому что ваше первоначальное предположение о 1,5-кратном сжатом размере было неправильным, что вызвало ошибку.

(Это может быть переполнение стека, как предлагается в другом ответе здесь, но я думаю, что выделение стека в 8 МБ является распространенным в настоящее время.)

1