Можно ли новые броски в случае кучи коррупции? - PullRequest
9 голосов
/ 06 июля 2011

В случае повреждения кучи может ли new бросить?

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

Ответы [ 4 ]

8 голосов
/ 06 июля 2011

Да, если куча повреждена, все может произойти. Бросить исключение возможно, но вряд ли. Что более вероятно, так это то, что он начнет разрушать память; если вам повезет , вы просто получите ошибку GPF / сегментации. Если вам не повезло, ваша программа продолжит работу с поврежденной кучей.

6 голосов
/ 06 июля 2011

(Перенесено из комментария к ответу по предложению Алса и расширено в лучшую или худшую сторону :-))

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

Если мы рассмотрим, какие типы повреждения может иметь куча:

  • Поврежденные записи, связанные с текущим состоянием кучи.

    • Распределение и/ или бесплатные списки.Коррупция может означать, что более поздние распределения кучи разыменовывают недействительные указатели, что некоторая часть кучи утечка оптом, что более поздний алгоритм выделения или удаления кучи вызывается во время new / new[] / delete / delete[] / malloc/ realloc / free бесконечно зацикливается и т. Д.
    • Синхронизация объектов.Состояние мьютексов, переменных условий и т. Д., Используемых реализацией подпрограмм кучи, может быть повреждено, что приведет к взаимным блокировкам, состояниям гонки, последующим сбоям во время вызовов связанных функций.
    • Счетчики, записывающие число элементов массива, построенных с помощьюnew[]: повреждение подразумевает, что delete [] уничтожит неправильное количество элементов.Если число будет уменьшено, некоторые объекты не будут уничтожены, что может привести к утечкам памяти, на которые они содержали указатели, невозможности уменьшить счетчики ссылок, оставить дескрипторы файлов открытыми, мьютексы останутся заблокированными, сегменты разделяемой памяти не будут уничтожены и т. Д. Если числоувеличивается, delete[] может получить доступ к памяти, содержащей массив - возможно, вызывая SIGSEGV - вызывая деструкторы, эквивалентные reintrepet_cast<> содержимого памяти в качестве объекта, подлежащего уничтожению.Это может попытаться разыменовать / удалить / освободить недопустимые указатели, закрыть «случайные» дескрипторы файла и т. Д.
  • Данные приложения

    • Объекты приложениясама создала через new и new[] может быть повреждена, что может привести к повреждению состояния программы, указателей и дескрипторов, которые они содержат и т. д. Проблемы могут проявляться любым количеством способов.

В более общем смысле в отношении кучи, в лучшем случае можно надеяться, что new будет выдавать, когда куча исчерпана, но даже это далеко не гарантировано - особенно в ОС, где только 1044 * выделяется только виртуальная память, и если последующие сбои страниц могутне удовлетворены тем, что они проявляются как SIGSEGV или подобные.

5 голосов
/ 06 июля 2011

Повреждение кучи - неопределенное поведение.new может throw, а может и нет.Распределитель памяти - это, в конечном счете, код, который считывает память кучи и выделяет память или подсказывает, что памяти нет.Теперь, если панель чтения повреждена, все сводится с ума!

3 голосов
/ 06 июля 2011

new зависит от некоторого распределения памяти, в зависимости от реализации.Это может быть malloc, HeapAlloc (например) или что-то еще, что кто-то определил в операторе new, который вы используете.Таким образом, вопрос заключается в том, как распределитель, используемый new, ведет себя, когда его структура данных повреждена.И это, конечно, зависит от реализации.

...