Это функция, которую я использую для распаковки буфера.
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);
после одной или двух итераций. Кто-нибудь может мне помочь?
Если ваш код в целом работает правильно, но не подходит для больших наборов данных, то это может быть связано с переполнением стека, как указано @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
,
c
не собирается становиться больше только потому, что вы увеличиваете datalength
, Вы, вероятно, перезаписываете после конца c
потому что ваше первоначальное предположение о 1,5-кратном сжатом размере было неправильным, что вызвало ошибку.
(Это может быть переполнение стека, как предлагается в другом ответе здесь, но я думаю, что выделение стека в 8 МБ является распространенным в настоящее время.)