Будет ли это выходить за рамки и не будет ли работать должным образом?

Я объявляю структуру внутри своего кода, а затем пытаюсь вставить ее в структуру данных, которую я написал. Однако я обеспокоен тем, что, поскольку я объявляю структуру внутри функции, после завершения функции структура данных будет указывать на мусор. Может кто-нибудь помочь с этим?

Вот код:

 void Class::function()
 {
  // do some stuff
  node newNode;
  newNode.memAddr = tempNode.memAddr+totalSize;
  newNode.size = tempNode.size-totalSize;
  lists[newNode.size>=512?64:(newNode.size>>3)].insert(&newNode);
 }

Редактировать: на самом деле я пытаюсь переписать malloc, поэтому вызов malloc() или new здесь не сработает. Есть ли способ, которым я мог бы переместить этот код в метод вставки, а затем заставить его работать так, чтобы он не выпадал из области вставки?


person samoz    schedule 22.04.2009    source источник


Ответы (6)


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

Редактировать: если вы, конечно, не скопируете память, на которую указываете при вставке.

person jfclavette    schedule 22.04.2009
comment
Забавно, что вы сказали это, потому что я на самом деле пытаюсь переписать malloc... :) - person samoz; 22.04.2009

Это почти наверняка вызовет ошибку. Проблема в том, что вы передаете адрес значения в стеке в список, который будет жить за пределами значения. Если в списке хранится node* типов, это будет неверно.

Чтобы заставить это работать, вам нужно выполнить одно из следующих действий.

  1. Пусть экземпляр списка хранит значения узла вместо node*.
  2. Выделите node* в куче перед его передачей. Это означает, что вам придется освободить его позже.
person JaredPar    schedule 22.04.2009
comment
Если Node не очень маленький, вы, вероятно, не захотите использовать вариант № 1. - person Steve Rowe; 22.04.2009
comment
@Steve, судя по ограниченному образцу, похоже, это так. Похоже, что это два значения: одно — указатель, а другое — size_t. Это достаточно мало, чтобы использовать по значению. - person JaredPar; 22.04.2009

newNode будет вне области видимости, а его адрес будет указывать на мусор (как заметил jfclavette.)

Но если случайно

 lists[newNode.size>=512?64:(newNode.size>>3)].insert(&newNode)

реализован для копирования newNode, то данные в этой копии вероятно будут в порядке, исходя из ограниченного фрагмента кода, который вы опубликовали.

person Dan Breslau    schedule 22.04.2009

Чтобы ответить на редактирование: нет.

person Bill Lynch    schedule 22.04.2009

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

Лучше выделить его в куче (используя новый) и освободить его в другое время.

Изменить: удалено примечание о том, что «Ваш компилятор должен был предупредить вас о взятии адреса объекта, выделенного в стеке (& newNode)». Ваш компилятор предупредит вас, если вы попытаетесь вернуть ссылку на объект стека, но не если вы просто попытаетесь получить указатель.

person Sebastian Good    schedule 22.04.2009
comment
Нет абсолютно ничего плохого в том, чтобы взять адрес объекта стека, и его компилятор не предупредит его об этом. Единственное допустимое предупреждение, если он возвращал адрес переменной стека. - person Don Neufeld; 22.04.2009
comment
Я не думаю, что видел, чтобы компиляторы предупреждали об этом. Есть много случаев, когда это нормально (например, сканирование и когорты), поэтому я думаю, что это может стать довольно раздражающим, если они это сделают. - person Peter; 22.04.2009

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

person Steve Rowe    schedule 22.04.2009