Разница между разыменованием указателя 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
В первом коде, поскольку мы не устанавливаем указатель, он принимает случайный адрес значения... Какой может иметь некоторое значение для мусора.
Но во втором случае указатель не указывает на какой-либо адрес, так что, очевидно, он потерпит неудачу