Разыменование удаленных указателей всегда приводит к нарушению прав доступа? - PullRequest
10 голосов
/ 24 мая 2010

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

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

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

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

Ответы [ 6 ]

18 голосов
/ 24 мая 2010

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

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

8 голосов
/ 24 мая 2010

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

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

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

5 голосов
/ 24 мая 2010

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

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

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

2 голосов
/ 24 мая 2010

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

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

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

1 голос
/ 24 мая 2010

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

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

Является ли этот вид аварии редким в в реальной жизни?

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

1 голос
/ 24 мая 2010

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...