15 августа 2020 г.

Задачка №26

Я тут обругался страшно на одно "нововведение" в библиотеке ZLib.

Упражнение: что не так в этом коде? В предположении, что все параметры указаны верно. Функция, если что, возвращает Z_OK:
function InitDeflate(const ACompressionLevel: Byte): TZStreamRec;
var
  Code: Integer;
begin
  FillChar(Result, SizeOf(Result), 0);
  Code := System.ZLib.deflateInit_(Result, ACompressionLevel, zlib_version, SizeOf(TZStreamRec));
  
  // ... далее идёт анализ Code
  // в данном случае Code = Z_OK
end;

Бонус-упражнение: найдите описание этого поведения в документации к ZLib.

Ответ.

9 комментариев:

  1. Может быть, не финализируется Result перед выполнением FillChar?

    ОтветитьУдалить
    Ответы
    1. ZLib - это C библиотека, она в проект подключается через уже скомпилированные .obj. Соответственно, C понятия не имеет про автофинализируемые типы Delphi. Следовательно, автофинализируемых типов в TZStreamRec нет.

      Удалить
  2. Может, оригинальная библиотека полагает TZStreamRec неперемещаемым (некопируемым)? Тогда result может указывать на временную переменную вместо настоящей цели присваивания, и если ZLib зачем-нибудь сохраняет указатель на z_streamp (TZStreamRec), он сломается. Пример: если есть функция f(var a: SomeType), то код a := f(a) будет выполнен как temp := f(a); a := temp, чтобы когда функция начнёт писать что-то в результат, это не вызвало неожиданных изменений ссылочного параметра a.

    ОтветитьУдалить
    Ответы
    1. О, мы как раз с этим столкнулись 2 года назад, и как раз в EurekaLog (модуль EPNG.pas)!
      Но только в 64-битном Delphi. 32-битный компилятор нормально работал, не выделял дополнительную память, а Result трактовал как var-параметр.
      Почему-то 64-битный компилятор делал именно так, как Вы пишете, создавал временную переменную. Почему так — я не помню уже, 2 года прошло. Видимо, из-за каких-то особенностей вложенных функций в Win64.

      Удалить
  3. че-то в конце многовато скобок.
    Одна лишняя?

    ОтветитьУдалить
  4. в описании этой функци указано всего 2 параметра, см https://zlib.net/manual.html

    ОтветитьУдалить
    Ответы
    1. deflateInit - это макрос, а реальная функция там как раз deflateInit_: https://refspecs.linuxbase.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/zlib-deflateinit.html

      Удалить

Можно использовать некоторые HTML-теги, например:

<b>Жирный</b>
<i>Курсив</i>
<a href="http://www.example.com/">Ссылка</a>

Вам необязательно регистрироваться для комментирования - для этого просто выберите из списка "Анонимный" (для анонимного комментария) или "Имя/URL" (для указания вашего имени и (опционально) ссылки на сайт). Все прочие варианты потребуют от вас входа в вашу учётку.

Пожалуйста, по возможности используйте "Имя/URL" вместо "Анонимный". URL можно просто не указывать.

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

Примечание. Отправлять комментарии могут только участники этого блога.