Почему разыменование NULL unique_ptr НЕ вызывает ошибку сегментации? [Дубликат]

да есть. добавьте

#!/usr/bin/env python

в начало файла и сделайте

chmod u+rx <file>

при условии, что ваш пользователь владеет файлом, в противном случае, возможно, отрегулируйте права группы или мира.

.py файлы под окнами связаны с python как программа для запуска при открытии их, как например, MS word запускается при открытии .docx.

3
задан Daniel H 7 September 2017 в 20:15
поделиться

5 ответов

Нет, это не гарантировано.

Например, что, если вы запускаете этот (злой) код до вашего примера:

mmap( ( void *) 0, ( size_t ) 4096, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0 );

Это отображает анонимную страницу с чтением / write на адрес 0.

0
ответ дан Andrew Henle 16 August 2018 в 10:10
поделиться

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

Подробнее:

  • С некоторые оптимизации, компилятор может обнаружить, что вы пытаетесь разыменовать NULL, решить, «что это запрещено, так что путь кода никогда не произойдет» и избавиться от обычного кода очистки функции; это приведет к тому, что ваша программа сместится в любую функцию, которая будет следующей в выходном двоичном файле.
  • Если компоновщик не ставит функцию рядом, а какой-то другой тип значения, он может попытаться выполнить , что , что либо приведет к проблеме, потому что оно сгенерировало незаконную инструкцию, либо проблему, потому что этот другой объект может быть помечен операционной системой не исполняемым.
  • Некоторые встроенные системы наделены У меня есть виртуальная память, поэтому на самом деле у меня есть некоторые значения в нулевом адресе памяти и с радостью дадут вам все, что бы там ни было.
  • Насколько мне известно, носовые демоны нуждаются в аппаратной поддержке, так что это маловероятный результат. Если это произойдет, не говорите, что вас не предупредили.
  • Как указано в комментариях @hvd, компилятор может просто пропустить строку как мертвое хранилище.

Если по какой-то причине вы хотите сгенерировать segfault, гораздо лучший способ сделать это с помощью

kill(getpid(), SIGSEGV);

(после включения соответствующих заголовков). Это отправляет сигнал segfault без какого-либо фактического нарушения сегментации. Если вы действительно хотите на самом деле совершить нарушение сегментации, вам лучше всего отобразить карту, а затем отменить какую-либо страницу (это зависит от ОС), а затем попытаться получить доступ к указателю на эту страницу.

2
ответ дан Daniel H 16 August 2018 в 10:10
поделиться
  • 1
    В этом случае я думаю, что несколько более правдоподобная оптимизация просто заключается в том, что компилятор замечает, что в хранилище никогда не будет следовать загрузка, поэтому бессмысленно и может быть удалено. Поскольку магазин тогда никогда не бывает, никакого segfault. – hvd 7 September 2017 в 20:30
  • 2
    @hvd Возможно, но есть моменты, когда Clang действительно удаляет конец такой функции. Это может быть только с __builtin_unreachable. – Daniel H 7 September 2017 в 20:31
  • 3
    Да, тип оптимизации, о котором вы описали, действительно имеет место, чаще всего, когда другие оптимизации показывают, что в определенном кодовом пути значение указателя ровано гарантировано как null, из моего опыта. В коде OP хранилище принадлежит выделенной памяти malloc, и компилятору необходимо будет разрешить выполнение malloc. :) – hvd 7 September 2017 в 20:39
  • 4
    @hvd Да, я предполагал, что это всего лишь мотивирующий пример. Когда я явно попробую это (C ++, потому что Compiler Explorer не поддерживает только C), Clang генерирует недопустимый код операции, когда я назначаю нулевой указатель, но если я изменю [0] на [2], он пытается сохранить 17 по адресу 0x8. Если я добавлю __builtin_unreachable();, он удалит весь код для main. Но поскольку это неопределенное поведение, вы, конечно, не можете рассчитывать на это. – Daniel H 7 September 2017 в 20:46
  • 5
    Если вы действительно хотите совершить нарушение сегментации, вам лучше всего сделать карту, а затем отобразить некоторую страницу . И даже это может привести к вам SIGBUS вместо SIGSEGV, если вы это сделаете это "неправильно" путь. – Andrew Henle 7 September 2017 в 22:00

Сегфафт не гарантируется стандартом C.

Вызов недопустимого указателя вызывает неопределенное поведение .

4
ответ дан dbush 16 August 2018 в 10:10
поделиться

Одним словом, нет.

Цитата из Wikipedia :

Разыменование указателя NULL обычно приводит к попытке чтения или записи из памяти, которая не отображается - вызывает ошибку сегментации или нарушение доступа. Это может представлять собой проявителя в виде сбоя программы или быть преобразовано в исключение, которое может быть обнаружено. Однако есть определенные обстоятельства, когда это не так. Например, в режиме реального времени x86 адрес 0000: 0000 является читаемым и обычно записывается на запись, поэтому разыменование нулевого указателя является абсолютно корректным, но обычно нежелательным действием, которое может привести к неопределенному, но не аварийному поведению в приложении. Также обратите внимание, что бывают случаи, когда разыменование NULL является преднамеренным и четко определенным; например, код BIOS, написанный на C для 16-разрядных устройств реального времени x86, может записывать IDT на физическом адресе 0 машины путем разыменования указателя NULL для записи. Компилятор также может оптимизировать разыменование указателя NULL, избегая ошибки сегментации, но вызывая другое нежелательное поведение ...

В C поведение разыменования нулевого указателя есть undefined .

Также проверьте этот wild example указателя нулевого класса разыменованный, но который все еще работает просто отлично.

В принципе, не делайте этого, но тогда вы знали, что:)

9
ответ дан djhaskin987 16 August 2018 в 10:10
поделиться

Нет, программа не гарантируется segfault. Выделение указателя , которому было присвоено недопустимое значение, - это неопределенное поведение , а в стандарте четко указано, что неопределенное поведение не предъявляет никаких требований. Он может завершить выполнение программы, но это не обязательно; он может даже полностью игнорировать ситуацию:

3.4.3 поведение неопределенного поведения

1 при использовании непереносимой или ошибочной программной конструкции или ошибочных данных, для которых это Международный стандарт не налагает никаких требований

2 ПРИМЕЧАНИЕ. Возможное неопределенное поведение варьируется от полного игнорирования ситуации с непредсказуемыми результатами, поведения во время трансляции или выполнения программы документированным образом, характерным для окружающей среды (с или без выдачи диагностическое сообщение), до завершения перевода или выполнения (с выдачей диагностического сообщения).

0
ответ дан Stephan Lechner 16 August 2018 в 10:10
поделиться
Другие вопросы по тегам:

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