Пользовательский распределитель стека, переопределение удаления


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

В настоящее время у меня есть;

static char contextStack[CONTEXT_MAX_SIZE];
static char *top = &contextStack[0];

И я переопределяю оператор new базового класса, который наследуется

static void *operator new(size_t size) {
  void *Result;
  Result = top;
  top = top + size;
  return Result;
};

Проблема в том, как бы я реализовал оператор delete, чтобы вытащить его из стека? Это не говорит мне, насколько большим был предмет? Должен ли я хранить размер каждой записи в массиве?

(p. s) последний созданный всегда первый, кто будет удален. И соответствует стеку.

4 2

4 ответа:

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

Если вы выделяли память в порядке убывания (как обычно в стеке), вы можете сохранить размер в самой стопке. Выполните арифметику указателя, чтобы получить новый Result (top - requested_size), затем уменьшите sizeof(int), сохраните размер и установите указатель top таким, чтобы он был этим указателем.

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

Должен ли я хранить размер каждой записи в массиве?

Вы можете использовать отдельную область хранения, или вы можете использовать стратегию, которой часто следуют реализации malloc: они хранят размер в известном месте перед указателем, который они возвращают вам. Когда вы вызываете free, они проверяют местоположение непосредственно перед указателем, который вы передаете, захватывают размер оттуда и приступают к освобождению.

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

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

Если вы используете класс шаблона для создания стека, вам не нужно знать размер каждого элемента, это гораздо проще .

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

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