Как создать экземпляр класса с переменным размером в определенной области памяти? - PullRequest
1 голос
/ 24 мая 2019

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

uint32_t packetHeader;
uint8_t packetPayload[];
uint32_t packetChecksum;

Когда мы создаем пакет, сначала мы хотели бы, чтобы его адрес в памяти был заданным смещением в файле отображения памяти, которыйЯ думаю, что можно сделать с размещением - new().Тем не менее, мы также хотели бы, чтобы packetPayload не был указателем на некоторую память из кучи, а являлся смежным с остальной частью класса (поэтому мы можем избежать memcpy перехода из кучи в наш конечный выходной файл)

т.е.

Memory

Beginning of class  | BOC + 4 | (length of Payload) |
Header                Payload   Checksum

Будет ли это достижимо с помощью аргумента length для конструктора класса Packet?Или мы должны были бы шаблонировать этот класс для полезных нагрузок переменного размера?

Ответы [ 2 ]

1 голос
/ 24 мая 2019

Забудьте о попытке сделать так, чтобы макет вашего класса. Вы будете бороться с языком C ++ весь день. Вместо этого класс, который обеспечивает доступ к двоичной структуре (в разделяемой памяти). Но сам экземпляр класса не будет в общей памяти. И диапазон байтов в совместно используемой / отображенной памяти вообще не будет объектом C ++, он просто существует в диапазоне адресов сопоставления файлов.

Предположительно длина фиксирована с момента создания? Если это так, то вы можете безопасно кэшировать длину, указатель на контрольную сумму и т. Д. В вашем объекте доступа. Так как этот кэш не находится внутри файла, вы можете хранить все, что захотите, как хотите, не заботясь о его макете. Вы даже можете использовать виртуальные функции-члены, потому что v-таблица собирается в экземпляре класса, а не в диапазоне двоичного файла.

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

0 голосов
/ 24 мая 2019

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

Сказав это - вам понадобится один из:

  • packageOffset является указателем
  • Элемент длины полезной нагрузки
  • Элемент смещения контрольной суммы

и вы захотите использовать именованный конструктор идиома , который принимает длину выделения и выполняет как распределение, так и настройку элемента offset / length / pointer для значения, соответствующего длине.

...