Вызов delete [] для динамического массива объектов не освобождает память?

В следующем коде:

int main(int argc,char * argv[]){
int * ptr;
ptr = 0; // tried also with NULL , nothing changes
ptr = new int[10]; // allocating 10 integers
ptr[2] = 5;
ptr[15] = 15;  // this should cause error (seg fault) - but it doesn't

cout << ptr[2] << endl;
cout << ptr[15] << endl;  // no error here

delete [] ptr;

cout << ptr[2] << endl;   // prints the value 5
cout << ptr[15] << endl;  // prints the value 15
}

Результат выполнения:

5
15
5
15
  1. Как мог существовать элемент с индексом 15, если я выделяю только 10?
  2. Почему указатели все еще имеют значения после освобождения всего массива?

Я попытался удалить с одним выделением, как это:

int * ptr;
ptr = 0;
ptr = new int;
*ptr = 5;
cout << *ptr << endl;
delete ptr ;
cout << *ptr << endl;

Результат нормальный:

5
0

Протестировано с gcc 4.7.2 и gcc 4.1.2 на fedora 17 и другой платформе (SLC5 — Linux на основе Red Hat), чтобы убедиться, что она не зависит от компилятора. Что я здесь не так делаю?

2

Решение

  1. Элемент за пределами заданного размера массива существует, потому что память там существует. Делать что-либо с этим незаконно и приводит к неизвестности.

  2. Освобождение означает, что память больше не выделена для вас. Это не значит, что кто-то пошел туда и почистил. Но доступ к тому, что от вас осталось, является незаконным и ведет к неизвестному.

9

Другие решения

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

В основном вы получите ошибку сегментации, потому что вы обращаетесь к памяти других приложений. На этот раз вам просто «повезло». Или, как я бы назвал, «неудачным», потому что вы не можете сразу сказать из исполнения, что ваша программа имеет ошибки памяти.

1

Разыменование удаленного указателя является неопределенным поведением, как определено стандартом C ++. И это только неопределенное поведение. Вы можете потерпеть крах, вы можете получить 0, вы можете получить то, что было там ранее, или 42. В этом месте по определению нет «нормального» поведения.

1
По вопросам рекламы [email protected]