Подтвердить что ты не робот

Является ли разыменование неверных указателей законным, если преобразование lvalue-to-rvalue не происходит

Попробуй, как я мог, самый близкий ответ, который я видел, this, с двумя полностью противоположными ответами (!)

Вопрос прост, является ли это законным?

auto p = reinterpret_cast<int*>(0xbadface);
*p;  // legal?

Мое отношение к делу

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

4b9b3361

Ответ 1

[basic.compound] говорит:

Каждое значение типа указателя является одним из следующих:

  • указатель на объект или функцию (указывается, что указатель указывает на объект или функцию) или
  • указатель за концом объекта ([expr.add]) или
  • значение нулевого указателя ([conv.ptr]) для этого типа или
  • неверное значение указателя.

В процессе устранения мы можем сделать вывод, что p является недопустимым значением указателя.

[basic.stc] говорит:

Направление с помощью недопустимого значения указателя и передача недопустимого значения значение указателя для функции deallocation имеет поведение undefined. Любые другое использование недопустимого значения указателя имеет определенную реализацию поведение.

Как говорят, оператор косвенности выполняет косвенное обращение [expr.unary.op], я бы сказал, что выражение *p вызывает UB независимо от того, используется ли результат или нет.

Ответ 2

... некоторые платформы ловушки для косвенных ссылок для недействительных указателей.

Большинство ловушек ловушки недействительного доступа к адресам. Это никоим образом не противоречит этой проблеме. Вопрос о том, что происходит в *p;, сводится к тому, происходит ли попытка на самом деле получить неверный адрес или нет.

Вопрос об извлечении очень похож на основная проблема 232 (косвенность через нулевой указатель). Как вы уже указали, *p; является отброшенным значением выражения, и как таковой преобразование lvalue-to-rvalue ( "выборка" ):

Tom Plum:

... это только акт "выборки", преобразования lvalue-to-rvalue, который вызывает неправильное поведение или undefined.

И впоследствии:

Примечания от совещания в октябре 2003 года:

Мы согласились, что подход в стандарте выглядит нормально: p = 0; *p;по сути, не является ошибкой. Преобразование lvalue-to-rvalue дало бы ему undefined.


Что касается того, создает ли или нет reinterpret_cast<int*>(0xbadface) допустимый указатель, действительно, в реализациях со строгой безопасностью указателя, это не будет безопасным образом указателем, и как таковой является недопустимым, и любое его использование - UB.

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