Разыменование удаленных указателей всегда приводит к Нарушению прав доступа?

У меня есть очень простой код C++ здесь:

char *s = new char[100];
strcpy(s, "HELLO");
delete [] s;
int n = strlen(s);

Если я выполняю этот код от Visual C++ 2008 путем нажатия F5 (Start Debugging) это всегда приводит к катастрофическому отказу (Нарушение прав доступа.) Однако начинающий этот исполняемый файл вне IDE или использующий Ctrl+F5 IDE (Запускаются без Отладки) не приводит ни к какому катастрофическому отказу. Каково могло быть различие?

Я также хочу знать, возможно ли устойчиво воспроизвести катастрофический отказ Нарушения прав доступа, вызванный от доступа к удаленной области? Действительно ли это - вид катастрофического отказа, редкого в реальной жизни?

10
задан Gant 24 May 2010 в 10:29
поделиться

6 ответов

Доступ к памяти через удаленный указатель является неопределенным поведением. Вы не можете ожидать надежного / повторяемого поведения.

Скорее всего, это «работает» в одном случае, потому что строка все еще «сидит там» в теперь доступной памяти - = но вы не можете полагаться на это. VS заполняет память значениями отладки, чтобы ускорить сбои и найти эти ошибки.

19
ответ дан 3 December 2019 в 14:05
поделиться

Разница в том, что отладчик, и отладочные библиотеки, и код, собранный в режиме "отладки", любят ломать то, что должно ломаться. Ваш код должен ломаться (потому что он обращается к памяти, которая ему больше технически не принадлежит), поэтому он легче ломается, когда компилируется для отладки и запускается в отладчике.

В реальной жизни вы, как правило, не получаете таких незаметных уведомлений. Все эти вещи, которые заставляют вещи ломаться, когда они должны ломаться в отладчике... эти вещи дороги. Поэтому в релизе это проверяется не так строго. Вы можете в 99 случаях из 100 обойтись освобождением памяти и обращением к ней сразу после этого, потому что библиотеки времени выполнения не всегда сразу отдают память обратно в ОС. Но в сотый раз память либо исчезнет, либо ею завладеет другой поток, и вы получите длину строки, которая уже не строка, а 252462649-байтовый массив дерьма, устремляющийся в нераспределенную (а значит, несуществующую, насколько это должно волновать вас или среду выполнения) память. И почти ничего не говорит вам о том, что только что произошло.

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

9
ответ дан 3 December 2019 в 14:05
поделиться

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

Здесь вы найдете объяснение того, как вы можете контролировать поведение вне отладчика: http://msdn.microsoft.com/en-us/library/w500y392%28v=VS.80%29. aspx

1
ответ дан 3 December 2019 в 14:05
поделиться

Разыменование указателя после delete является неопределенным поведением - может произойти что угодно, включая, помимо прочего:

  • повреждение данных
  • нарушение доступа
  • не видно эффекты

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

5
ответ дан 3 December 2019 в 14:05
поделиться

Я также хочу знать, возможно ли это стабильно воспроизводить доступ Сбой нарушения из-за доступа удаленная область?

Вместо простого delete вы можете рассмотреть возможность использования встроенной функции, которая также устанавливает значение удаленного указателя на 0 / NULL. Обычно это приводит к сбою, если вы на него ссылаетесь. Однако он не будет жаловаться, если вы удалите его второй раз.

Редко ли такое падение в в реальной жизни?

Нет, этот вид сбоев, вероятно, стоит за большинством сбоев, которые мы с вами наблюдаем в программном обеспечении.

1
ответ дан 3 December 2019 в 14:05
поделиться

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

Нарушение прав доступа вызвано чтением / записью памяти, которая недоступна, обычно не выгружается в процесс. Различные служебные программы отладки памяти во время выполнения используют механизм разбиения по страницам для отслеживания недействительных обращений к памяти без серьезных потерь времени выполнения, которые могут возникнуть при проверке программной памяти.

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

2
ответ дан 3 December 2019 в 14:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: