zlib - надувать работает только после двойного вызова inflateinit

У меня есть некоторые предварительно сжатые данные (сжатые с помощью zlib-flate в Linux) внутри моей оперативной памяти. Чтобы использовать эти сжатые данные, я хочу сжать их с помощью zlib и надуть.

У меня нет динамического управления памятью в этой системе, но я предоставил достаточно большой буфер для несжатых данных. Проблема в том, что если я вызываю подпрограмму inflate после вызова подпрограммы inflateInit, я получаю необработанное исключение.

Но если я вызову функцию inflateInit два раза, следующая инфляция (= распаковка) работает нормально, и я получаю правильные распакованные данные в предоставленный буфер. Это странно не так ли?

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

Позвольте мне показать вам поведение:

  1. initInflate
  2. раздувать > неудачно

новый пробег..

  1. initInflate
  2. initInflate
  3. раздувать > успех

новый пробег..

  1. initDeflate
  2. deflate (успех, но я не использую результат)
  3. initInflate
  4. раздувать > успех

Где-то есть массив, содержащий сжатые данные:

uint8_t src [] = {.....};

Это мой буфер, который определенно достаточно велик, чтобы содержать полные распакованные данные.

#define BUF_SIZE 1000
uint8_t buf[BUF_SIZE];

А это код моей распаковки:

z_stream strm;

strm.zalloc = Z_NULL;
strm.zfree  = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = srcLen;
strm.next_in = src;
strm.avail_out = BUF_SIZE;
strm.next_out = buf;
strm.data_type = Z_BINARY;

inflateInit(&strm);
inflateInit(&strm); // the follwing inflate only works with this second init

inflate(&strm, Z_NO_FLUSH);

Я вижу, что член потока state меняется с 0x40193678 после первой инициализации на 0x40195250 после второй инициализации (возможно, это важная информация для вас). И обе инициализации являются ответом с Z_OK.

И теперь я надеюсь, что вы можете мне помочь ..


person PIC-Nico    schedule 07.06.2018    source источник
comment
Что именно здесь означает неудача и успех? Что возвращает inflate()?   -  person Mark Adler    schedule 08.06.2018
comment
Если 'inflate()' был успешным, возвращается Z_STREAM_END. Если инфляция не удалась (например, потому что я вызвал inflateInit() только один раз), кажется, что я сталкиваюсь с необработанным исключением, потому что мой программный счетчик скачет в никуда (вектор загрузки или что-то подобное - программа аварийно завершает работу).   -  person PIC-Nico    schedule 08.06.2018
comment
Что вы имеете в виду, говоря, что у меня нет динамического управления памятью в этой системе?   -  person Mark Adler    schedule 08.06.2018
comment
В моей программе нет функции malloc. Поэтому я предоставил достаточно большой буфер (я знаю размер несжатых данных), чтобы zlib мог обрабатывать полные данные за один проход.   -  person PIC-Nico    schedule 08.06.2018


Ответы (1)


Что он делает, так это выделяет память для потока дважды, используя только второе выделение. Я могу только догадываться, что вы перезаписываете только память, выделенную первым inflateInit(), из-за какой-то другой ошибки в вашей программе. Перезапись аварийно завершает работу inflate() при попытке использовать первое выделение, но завершается успешно при использовании второго распределения, которое не перезаписывается другой ошибкой.

person Mark Adler    schedule 08.06.2018
comment
Может быть, вы можете помочь мне понять поведение немного лучше. Будет ли библиотека всегда выделять память (с ее внутренними стандартными функциями, если для zalloc, zfree и opaque установлено значение Z_ZERO), даже если я уже предоставил достаточно большой буфер? Или библиотеке нужны другие временные буферы (для внутренних целей, кроме необработанного буфера результата/назначения? Тем не менее, спасибо за вашу поддержку! - person PIC-Nico; 08.06.2018
comment
Я мог понять это внутри функции inflate_fast() в строке 114. переменная bits становится странным значением 0xFFFFFF2, которое кажется результатом bits - op, где op больше, чем bits. И это приводит к тому, что ошибочное значение указателя записывается в strm->next_in в строке 299. :-( - person PIC-Nico; 08.06.2018
comment
Независимо от выходного буфера, который вы ему задали, inflateInit() всегда будет выделять память для собственного использования, используя malloc(), если вы дадите Z_NULLs. Позже inflateEnd() воспользуется free() для освобождения памяти. - person Mark Adler; 08.06.2018
comment
Кажется, проблема была вызвана многопоточностью. Я мог бы исправить описанную проблему, добавив критическую секцию. - person PIC-Nico; 27.06.2018