Что делает команда delete для памяти, для указателей в C++?
Возможный дубликат:
C++ delete - удаляет мои объекты, но я все еще могу получить доступ к данным?
Можно ли получить доступ к памяти локальной переменной за пределами ее объема?
Я не понимаю, что действительно делает delete
, когда я хочу освободить выделенную память new
. В книге C++ Premiere написано:
Это удаляет память, на которую указывает указатель ps; он не удаляет сам указатель ps. Вы можете повторно использовать ps, например, чтобы указать на другое новое распределение. Вы всегда должны балансировать использование нового с использованием delete; в противном случае вы можете завершить утечку памяти, то есть память, которая была выделена, но больше не может использоваться. Если утечка памяти становится слишком большой, она может привести к остановке работы программы.
Таким образом, я понимаю, что delete
должен удалить значение в памяти, к которому относятся точки pinter. Но это не так. Здесь мой эксперимент:
int * ipt = new int; // create new pointer-to-int
cout << ipt << endl; // 0x200102a0, so pointer ipt points to address 0x200102a0
cout << *ipt << endl; // 0, so the value at that address for now is 0. Ok, nothing was assigned
*ipt = 1000; // assign a value to that memory address
cout << *pt << endl; // read the new value, it is 1000, ok
cout << *((int *) 0x200102a0) << endl; // read exactly from the address, 1000 too
delete ipt; // now I do delete and then check
cout << ipt << endl; // 0x200102a0, so still points to 0x200102a0
cout << *ipt << endl; // 1000, the value there is the same
cout << *((int *) 0x200102a0) << endl; // 1000, also 1000 is the value
Итак, что действительно делает delete
?
Ответы
Ответ 1
Подумайте о памяти как о большом складе с большим количеством ящиков, чтобы положить вещи. Когда вы называете "новым", персонал склада находит неиспользованную коробку, достаточно большую для ваших нужд, записывает эту коробку как принадлежащую вам (чтобы она не предоставлялась кому-то еще), и дает вам номер этого окна, чтобы вы могли поставить ваши вещи в него. Это число будет "указателем".
Теперь, когда вы "удаляете" этот указатель, происходит обратное: персонал склада отмечает, что этот конкретный ящик снова доступен. В отличие от реальных сотрудников склада, они ничего не делают с коробкой, поэтому, если вы посмотрите на нее после "удаления", вы можете увидеть свои старые вещи. Или вы можете увидеть чужие вещи, если коробка была переназначена тем временем.
Технически вам не разрешается заглядывать в свою коробку после того, как вы вернули ее в пул, но это несколько странный склад без ключей или охранников, поэтому вы все равно можете делать все, что хотите. Однако это может вызвать проблемы с новым владельцем коробки, поэтому ожидается, что вы будете следовать правилам.
Ответ 2
Ваш эксперимент имеет undefined behavior
как только вы разыщите указатель после инструкции delete
. Все может случиться, что делает ваш эксперимент бесполезным.
Что делает delete
(not delete[]
)? Он освобождает хранилище, на которое указывает его аргумент. Это вызовет запуск деструктора объекта, хранящегося в этом месте. Доступ к удаленному хранилищу вызывает неопределенное поведение (часто это segmentation fault
). Нет никаких гарантий того, что память действительно будет возвращена операционной системе или что-то еще.
Ответ 3
delete
делает память доступной для последующих запросов через new
. Независимо от того, скрещивается ли он с контентом, он не определен. Так как быстрее оставить содержимое таким, каким оно есть, в режиме выпуска, вероятно, появится, что память все еще "доступна". В режиме отладки он может зашифроваться с помощью магических чисел.
То, что вы здесь испытываете, называется "неопределенным поведением" в C++. В этом случае неопределенное поведение вызвано доступом к куску памяти после его окончания жизни. Только не делай этого.
Ответ 4
Выделение указателя после delete
-ing - это неопределенное поведение, поэтому все может случиться.
Обычно delete
отметки памяти как освобожденные, поэтому их можно повторно использовать позже, но это сложная тема.
Правило большого пальца: никогда, никогда не используйте new
и delete
напрямую (за исключением реализации make_unique
, которого по какой-то причине не хватает стандарту); используйте RAII.
Ответ 5
Оператор delete
освобождает память, которая ранее была назначена с использованием new
оператора. Это означает, что память теперь доступна для использования системой, например, когда есть другое использование new
позже. Однако он не очищает данные в памяти. Указатель по-прежнему будет указывать на тот же адрес в памяти, но доступ к этому блоку приведет к неопределенному поведению.
Рекомендуется delete
указатель на NULL
(или nullptr
в С++ 11) после delete
его. Любое последующее delete
будет безобидным.
Ответ 6
delete
возвращает память обратно в систему - в основном, она больше не зарезервирована для вашей программы. Это не означает, что значения в памяти будут немедленно перезаписаны, но это может быть в любой момент после delete
. В большинстве случаев одна и та же память перераспределяется в будущем в вашей собственной программе.