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

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

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

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

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

Ответы [ 4 ]

21 голосов
/ 12 октября 2011

Невозможно ответить на этот вопрос без полного понимания того, как каждая из этих упакованных записей используется в коде вашего приложения. Это то же самое, что спросить «Должен ли я изменить это объявление переменной с 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;
7 голосов
/ 12 октября 2011

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

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

1 голос
/ 12 октября 2011

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

Обновление:

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

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