Является ли `0x2` нулевым указателем в C ++? - PullRequest
1 голос
/ 09 апреля 2020

В следующем коде:

int* p = (int*)0x2;
*p = 1;

Этот код приводит к ошибке сегментации. Но:

int* p = (int*)0x2;
cout << (p == nullptr);

Вывод 0. Итак:

  1. Указатель, указывающий на адрес 0x2, действительно пустой указатель (который вызывает ошибку сегментации)?
  2. Как я могу обрабатывать такие случаи, как 0x2 с помощью операторов if ? (Я имею в виду, обрабатывать случаи, в которых разыменование может вызвать сбой сегментации. Потому что, как вы видите в if (p == nullptr), этот случай не обрабатывается).
  3. Что такое адреса, отличные от 0x2, которые разыменовывают указатель, указывающий на они вызывают ошибку сегментации и почему?

Ответы [ 4 ]

4 голосов
/ 09 апреля 2020

Единственное целое значение, конвертируемое в std::nullptr, равно 0.

Является ли 0x2 действительным адресом памяти или нет, зависит от вашей программы. Если вы просто используете псевдоним этой области памяти как int*, это неопределенное поведение, и вам повезло, что вы получили ошибку сегментации.

Способ, которым вы «обрабатываете» такие случаи, как 0x2, заключается в структурировании вашей программы. каким-то образом, чтобы гарантировать, что 0x2 является действительным адресом памяти. Одного адреса часто недостаточно. Трудно гарантировать отсутствие висящих указателей в большой кодовой базе, но, используя интеллектуальные указатели и ссылки разумно, мы можем разработать довольно безопасную программу. Часто вы можете избежать передачи по значению.

Какие адреса, кроме 0x2, разыменование указателя на них вызывает ошибку сегментации и почему?

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

1 голос
/ 09 апреля 2020

Указатель, указывающий на адрес 0x2, действительно является нулевым указателем

0x2 не является константой нулевого указателя.

Значение равно нулю однако не уточняется. Теоретически это может быть 2. Но в большинстве систем это 0. Выходные данные, которые вы показываете, показывают, что в вашей системе значение null не имеет 2.

(что приводит к ошибке сегментации) ?

Косвенное обращение через нуль - не единственное, что вызывает ошибку segfault.

Как я могу обрабатывать такие случаи, как 0x2, с помощью операторов if? (Я имею в виду, обрабатывать случаи, в которых разыменование может вызвать сбой сегментации.

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

Какие адреса, кроме 0x2, разыменование указателя на них вызывает ошибку сегментации и почему?

С точки зрения C ++: доступ к любому объекту за пределами срока его службы приводит к тому, что поведение программы не определено. Если объекта по адресу X нет, то доступ к * X является неопределенным поведением, если не указано иное. Объекты создаются путем определения переменных и с использованием new -выражений.

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

1 голос
/ 09 апреля 2020

Действительно ли указатель, указывающий на адрес 0x2, является нулевым указателем (который вызывает ошибку сегментации)?

Нет, это не нулевой указатель, поскольку вывод 0 доказан.

Как я могу обрабатывать такие случаи, как 0x2 с помощью операторов if? (Я имею в виду, обрабатывать случаи, в которых разыменование вызывало бы ошибку сегментации. Потому что, как вы видите в случае, если (p == nullptr), этот случай не обрабатывается).

Вы не можете. Нет списка всех адресов, которые ваша программа может использовать.

Какие адреса, кроме 0x2, разыменование указателя на них вызывает ошибку сегментации и почему?

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

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

1 голос
/ 09 апреля 2020

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

См. Также Что такое ошибка сегментации?

...