Ответ
Разыменование нулевого указателя (например, *ptr, где ptr == nullptr) или вызов метода через такой указатель (ptr->method()) приводит к неопределенному поведению (Undefined Behavior, UB) согласно стандарту C++.
Что это значит на практике? Компилятор и исполняющая среда не гарантируют никакого конкретного результата. Возможные последствия включают, но не ограничиваются:
- Немедленный крах программы: Наиболее частый сценарий. Операционная система обнаруживает попытку доступа к защищенной памяти по адресу 0 и отправляет сигнал (например,
SIGSEGVна Linux), вызывая аварийное завершение. - Тихий крах или порча данных: Программа может продолжить работу с некорректными данными, что позже приведет к непредсказуемым и трудноотлаживаемым ошибкам.
- Неожиданная оптимизация: Поскольку стандарт говорит, что UB «не должно происходить», компилятор может делать агрессивные предположения. Например, он может удалить целые ветки кода, которые, по его логике, ведут к UB.
Пример опасного кода и защита:
#include <iostream>
void unsafe(int* p) {
std::cout << *p << std::endl; // UB, если p == nullptr
}
void safe(int* p) {
// Всегда проверяйте указатель перед разыменованием
if (p != nullptr) { // или просто if(p)
std::cout << *p << std::endl;
} else {
std::cout << "Ошибка: передан нулевой указатель" << std::endl;
}
}
void safeWithReferences(int* p) {
// Использование ссылок на этапе проектирования API помогает избежать проблемы.
// Функция, принимающая ссылку, требует валидный объект.
}
int main() {
int* nullPtr = nullptr;
// unsafe(nullPtr); // Потенциальный крах (SIGSEGV)
safe(nullPtr); // Безопасная обработка
return 0;
}
Вывод: Разыменование nullptr — одна из самых распространенных и опасных ошибок в C++. Всегда инициализируйте указатели, проверяйте их на nullptr перед использованием и отдавайте предпочтение ссылкам и умным указателям (std::unique_ptr, std::shared_ptr), которые обеспечивают более строгую семантику владения.