Может ли разыменование указателя бросить? - PullRequest
1 голос
/ 30 сентября 2010

Я учу себя методам программирования с исключением режима безопасности;) и мне интересно, может ли разыменование указателя когда-либо вызвать исключение?Я думаю, что было бы полезно для всех программистов на C ++ знать все операции, которые гарантированно не генерируются, поэтому я был бы очень признателен, если бы кто-то мог составить такой список.

Ответы [ 4 ]

11 голосов
/ 30 сентября 2010

Разыменование простого указателя (T*) может привести к неопределенному поведению , если не существует допустимого объекта указанного типа, на который указывает указатель,Природа UB заключается в том, что результатом может быть что угодно , включая, помимо прочего, исключение C ++.Можно действительно представить реализацию, которая проверяла бы указатели на доступ и создавала исключение.Тем не менее, я сомневаюсь, что такая реализация C ++ когда-либо будет существовать (если вы можете сэкономить время выполнения, зачем использовать C ++?), И обычное поведение на большинстве платформ состоит в том, чтобы либо запутаться (если выделяется память)к процессу) или сбой .На некоторых платформах существуют способы перехвата таких сбоев (например, Windows Структурные исключения ).

Однако унарный operator*() может быть перегружен и обычно предназначен для интеллектуальных указателей и итераторов.Такие реализации, безусловно, могут делать все, что хотят их разработчики, включая, помимо прочего, создание исключения.Но опять же из-за накладных расходов во время выполнения обычные реализации интеллектуальных указателей проверяют только в отладочных сборках (обычно с использованием какой-либо формы утверждения), но не в сборках выпуска.(Заметным исключением являются итераторы в недавних реализациях Visual C ++, которые получают достаточно тепла для этого необычного поведения.)

Существует очень сильная традиция в C ++ различать ошибокпрограммист мог предотвратить (например, доступ к массиву вне границ) и ошибок, которые программисты не могли предотвратить (например, обрыв сетевого соединения).Для грубой скорости первые обычно приводят к UB , потому что проверка их каждый раз будет стоить производительности.Программистам следует проверять, где это уместно и необходимо.
Это различие можно увидеть в определении иерархии исключений стандартной библиотеки, которая подразделяется на предотвратимые std::logic_error и непригодные std::runtime_error.

1 голос
/ 30 сентября 2010

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

Вы можете перехватить исключения доступа к памяти, используя std::signal( my_handler, SIGSEGV );, хотя это все еще зависит от поддержки платформы, и Стандарт не позволяет вам преобразовать его в исключение C ++.

Я понимаю, что у Microsoft есть свои собственные "управляемые" исключения или еще что-то подобное, которые, возможно, могут быть обнаружены с помощью этого механизма и перестроены в соглашениях C ++. Или, может быть, это запрещено; Я не знаю.

0 голосов
/ 30 сентября 2010

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

Например:

int *p = 0xFFFFFFFF; // Invalid pointer
*p;                  // Dereferenced, but since it doesn't do anything there's no error
*p = 0;              // Dereferenced write, so it will halt and catch fire
0 голосов
/ 30 сентября 2010

разыменование происходит во время выполнения и на очень низком уровне (сборка / уровень машины), поэтому он не может ничего выбросить, однако он вызовет исключение, например EXCEPTION_ACCESS_VIOLATION или SegFault в linux / unix.1003 * (предполагается, что используются сырые указатели)

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