Разница между разыменованием указателя NULL и неинициализированным указателем

В блоках кода (С++)

#include<bits/stdc++.h>
using namespace std;
int main(){
    int *p;
    cout<<*p;
}

производит значение мусора, тогда как

#include<bits/stdc++.h>
using namespace std;
int main(){
    int *p=NULL;
    cout<<*p;
}

приводит к ошибке выполнения. Я ожидал ошибку времени выполнения для обоих (ideone производит ошибку времени выполнения для обоих), потому что оба являются плохими указателями. Как это можно объяснить?

Ответ 1

Ваше ожидание ошибки во время выполнения является ошибочным.

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

Это означает, что потенциальные симптомы варьируются от:

  • ничего не происходит
  • что-то происходит
  • происходит ошибка времени выполнения
  • ваш исходный код самопроизвольно редактируется для использования правильных стандартных заголовков вместо ошибочного взлома в реализации "бит"
  • Ваше отношение в разделе комментариев волшебным образом улучшено.
  • твоя кошка убита.
  • Ваша кошка не убита.
  • ваша кошка убита и не убита.
  • твоя кошка убивает себя
  • черная дыра открывается внутри вашей кошки
  • кошка открывается внутри черной дыры

и т.д.

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

Ответ 2

Ваш первый пример,

int *p;
cout << *p;

принимает дикий указатель и пытается разыменовать его. Что на другом конце этого указателя? Это системное местоположение, которое вызовет ошибку времени выполнения? Является ли это адресом x, другой переменной в вашей программе? Это часть памяти, которую использует ваш веб-браузер? Попытка разыменования и чтения или записи в это место undefined поведение, нет гарантии того, что произойдет (время путешествия было сообщено в крайних случаях).

Выделение нулевого указателя (указатель на адрес 0), однако также undefined, но, скорее всего, приведет к ошибке сегментации - a ошибка времени выполнения.

Ответ 3

В первом коде, поскольку мы не устанавливаем указатель, он принимает случайный адрес значения... Какой может иметь некоторое значение для мусора. Но во втором случае указатель не указывает на какой-либо адрес, так что, очевидно, он потерпит неудачу