Ничего, кроме "упакованных" записей - я должен это исправить?

Просматривая некоторый код в нашей устаревшей программе Delphi 7, я заметил, что везде, где есть запись, она помечена packed, Это, конечно, означает, что запись хранится побайтово и не выровнена для ускорения доступа ЦП. Упаковка, кажется, была сделана вслепую как попытка перехитрить компилятор или что-то в этом роде - в основном, оценивая несколько байтов памяти вместо более быстрого доступа

Пример записи:

TFooTypeRec = packed record
    RID                 : Integer;
    Description         : String;
    CalcInTotalIncome   : Boolean;
    RequireAddress      : Boolean;
end;

Должен ли я это исправить и сделать каждую запись нормальной или "не" упакованной? Или с современными процессорами и памятью это ничтожно мало и, вероятно, пустая трата времени? Есть ли какие-либо проблемы, которые могут возникнуть в результате распаковки?

4 ответа

Решение

Невозможно ответить на этот вопрос без полного понимания того, как каждая из этих упакованных записей используется в коде вашего приложения. Это то же самое, что спросить "Должен ли я изменить это объявление переменной с Int64 на Byte?"

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

Точно так же в вашем случае. Если запись должна быть упакована, то ее следует оставить упакованной. Если его не нужно упаковывать, то не стоит вредить, если его не упаковывать. Если вы не уверены или не можете сказать, тогда самый безопасный способ - оставить их такими, какие они есть.

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

  • постоянство рекордных значений
  • совместное использование значений записей с [потенциально] по-разному скомпилированным кодом
  • строгая совместимость с внешне определенными структурами
  • преднамеренное наложение макета типа на память с разной структурой

Это не обязательно исчерпывающий список, и все эти общие черты:

  • записи, содержащие серию значений в смежных байтах, на которые может и может положиться любой потенциальный производитель или потребитель записи без возможности вмешательства со стороны компилятора или других факторов

Я бы порекомендовал, чтобы (если это возможно и практично) вы определяли, для какой цели используется упаковка в каждом конкретном случае, и добавьте соответствующую документацию к самому объявлению записи, чтобы никому в будущем с тем же вопросом не пришлось проходить через это. процесс обнаружения, например:

  type
    TSomeRecordType = packed record
      // This record must be packed as it is used for persistence
      ..
    end;

    TSomeExternType = packed record
      // This record must be packed as it is required to be compatible
      //  in memory with an externally defined struct (ref: extern code docs)
      ..
    end;

Основная идея использования упакованных записей не в том, чтобы сэкономить несколько байтов памяти! Вместо этого речь идет о гарантии того, что переменные находятся там, где вы ожидаете, что они будут в памяти. Без такой гарантии было бы невозможно (или, по крайней мере, трудно) управлять памятью вручную в куче, записывать и читать из файлов.

Следовательно, программа может работать неправильно, если вы "распакуете" записи!

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

Обновить:

В вашем примере объявлен строковый тип. Это выглядит подозрительно, поскольку сохранение записи в двоичном файле не сохранит содержимое строки.

  • Упакованные записи имеют длину, точно такую ​​же, как у членов.
  • Никакая упакованная запись не оптимизирована (они выровнены -> следовательно выше) для лучшей производительности.
Другие вопросы по тегам