2015-08-13 1 views
2

Это функция, которую я использую для распаковки буфера.Сжатие буфера unzip с большой длиной данных

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

И это не работает нормально до сегодняшнего дня, когда я понял, что он выходит из строя с большим буфером данных (Ex: decryptedLength: 342792) на этой линии:

status = inflate (&stream, Z_SYNC_FLUSH); 

после одного или двух итераций. Кто-нибудь может мне помочь?

+0

Может быть, вы должны точно сказать, как он упал. BTW - может ли это проблема переполнения стека? 'char c [dataLength];' приблизительно. 600 000 символов. – 4386427

+0

Распаковка не расшифровывается. – EJP

ответ

2

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

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

char c[dataLength]; 

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

char* c = new char[dataLength]; 

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

delete[] c; 

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

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


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

+0

спасибо за помощь, но проблема не устранена. И спасибо за совет, я буду динамически распределять память. – Grace

+0

Добро пожаловать! Пожалуйста, также взгляните на ответ от @MarkAdler. Он поднимает точку, которая также вызывала у меня подозрение. Я не включил его, потому что я точно не знаю, как работает zlib.Просто попробуйте с 3 вместо 1,5 раза. Если это работает, вам необходимо динамически перераспределить буфер, чтобы увеличить его. – honk

+0

@Grace: Я добавил некоторые объяснения по вопросу «перераспределения» на мой ответ. – honk

1

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

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

+0

Спасибо за помощь !!! – Grace

Смежные вопросы