Удаление массива char не влияет на массив вообще - PullRequest
0 голосов
/ 31 января 2012

поэтому я выполняю этот код

#include <cstdlib>
#include <iostream>
int main()
{
    char *test = new char[10];
    strcpy(test, "Hello Ther");;
    std::cout << test << std::endl;
    delete[] test;
    std::cout << test << std::endl;
    return 0;
}

и вывод

Hello Ther

Hello Ther

Кажется, что оператор delete[] test ничего не делает ... Нет ошибок времени выполнения или компиляции вообще

полностью поставил меня в тупик

Ответы [ 3 ]

8 голосов
/ 31 января 2012

После delete[] массива массив больше не существует.Любой доступ через этот указатель после этого имеет неопределенное поведение.

delete[] должен вызывать деструкторы элементов массива и освобождать используемое им хранилище.Так как char не имеет деструктора, он просто освобождает хранилище.Освобождение хранилища только означает, что оно больше не используется.

FWIW, в вашем коде есть еще один случай неопределенного поведения."Hello Ther" имеет 11 элементов: в конце есть нулевой ('\0') терминатор.strcpy в том, что в буфер размером всего 10 элементов, поведение не определено.Вам необходим буфер с местом для 11 элементов: 10 символов «Hello Ther» плюс нулевой терминатор.

Этот тип ошибки, переполнение буфера, является распространенным источником уязвимостей в безопасности.Были известные подвиги такого рода ошибок, по крайней мере, с 1980-х годов.Было бы разумно избегать таких небезопасных примитивов и отдавать предпочтение безопасным современным (и под «современным» я имею в виду «с 1990-х годов»), например std::string.Потому что, вы знаете, это 21-й век.

3 голосов
/ 31 января 2012

Что вы ожидали?

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

2 голосов
/ 31 января 2012

В C ++ можно получить доступ к памяти независимо от того, выделена она или нет.Это вызывает неопределенное поведение, но нет никакой проверки, которая говорит, является ли данная память «доступной».Это твоя проблема.Это отличается от языков на основе ВМ, где доступ к памяти проверяется для вас.

Распространенная идиома, позволяющая избежать ошибок такого рода, заключается в следующем:

delete[] myArray;
myArray = NULL; // preferably "nullptr" in C++11

Любой доступ к NULL адрес отклонен процессором.Он предупредит ОС об ошибке (которая, вероятно, приведет к завершению вашей программы в segfault или эквивалентной ошибке).

Как упомянуто stonemetal, некоторые компиляторы / OS / allocaters проверят доступ к памяти в отладочных сборках, но выигралине делайте этого в режиме релиза для увеличения скорости.

Примечание. Если вы попытаетесь получить доступ к нераспределенной памяти в случайном порядке, вы столкнетесь с ошибками страницы, но это немного не в тему.

...