2015-03-22 3 views
-2

Если я пойду ...Программа вылетает при удалении указателя, указывающего на кучу?

int *foo = new int; 
foo += 1; 
delete foo;  

Большую часть времени он выходит из строя. Для этого есть причина? Я пытаюсь указать точку указателя на одно место вперед (4 байта). Благодарю.

Редактировать (шесть месяцев спустя): Это был первый вопрос, который я задал на SO, и это был глупый вопрос и заслужил downvotes. Его можно удалить, если он не предназначен для учащихся. Я действительно говорил о распределении int из четырех байтов в куче, а затем переместил указатель на четыре байта вперед, а затем удалил указатель int, по сути, уничтожив, что Бог знает, что приводит к неопределенному поведению. Спасибо за вашу помощь.

+5

Что бы вы ожидаете этот код делать? –

+0

Вы удаляете указатель на (возможно) нераспределенный адрес памяти; конечно, это сбой. – GoBusto

+0

Я узнал, что после каждого «нового» вам нужно использовать «delete», значит, это означает, что если вы выделяете память в куче, вы не можете переместить указатель? Или сделать это пустой указатель, прежде чем удалять это ответ? – Zebrafish

ответ

5

Необходимо передать в delete значение, которое возвращается new. Вы этого не делаете.

Я думаю, что вы смущены относительно того, что вы проходите до delete. Я думаю, что вы считаете, что delete foo удалит память, связанную с переменной. Это не так. Он удаляет память, адрес которой хранится в foo.

В качестве примера, это оправдано:

int* foo = new int; 
int* bar = foo; 
delete bar; 

Важно не имя переменной, а значение переменной.

Вот еще один пример:

int* arr = new int[10]; 
int* ptr = arr; 
for (int i; i < 10; i++) 
{ 
    *ptr = i; 
    ptr++; 
} 
delete[] arr; 

Для выполнения арифметических операций над указателями, и сохранить адрес, возвращенный new[], мы ввели дополнительную переменную. Я использовал массив, потому что не имеет смысла выполнять арифметику по указателю на одно значение.

Обратите внимание, что в приведенном выше коде это может быть написано более четко с использованием arr[i] = i и поэтому избегать необходимости использования второй переменной указателя. Я написал это, как показано выше, чтобы проиллюстрировать, как вы можете кодировать, когда арифметика указателя является правильной опцией.

+0

Значит, это означает, что я должен указать его на одно и то же место, прежде чем я удалю его? Или движет указатели что-то, что не сделано? – Zebrafish

+1

@TitoneMaurice Вы можете перемещать указатели, но вы, вероятно, захотите иметь один указатель, который всегда будет указывать на память, которую вам нужно удалить. Например, вы можете назначить другой указатель на основе значения 'foo'. – emlai

+0

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

6

Единственное, что вы можете смело переходить к delete является то, что вы получили, когда вы назвали new или nullptr, в этом случае delete не будет ничего делать.

Вы изменили значение указателя - поэтому это не «что-то вы получили, когда вы назвали new»

Смежные вопросы