Есть ли в C++ эквивалент NullPointerException
И Java, и C#, и, возможно, многие другие языки также имеют предопределенный класс исключений, который выдается, когда нулевой параметр используется там, где он не должен. Есть ли что-нибудь подобное в C++? Если нет, есть ли другое предопределенное исключение, которое я могу использовать, или я должен определить свое собственное?
6 ответов
Разыменование NULL-указателя - неопределенное поведение в C++, что означает, что код может работать. Исключение не гарантируется. Вы можете использовать
std::invalid_argument
исключение (предоставить значимое значение для него - "p is NULL"
), но вы должны будете сделать проверку самостоятельно.
Обычно в C++ (или C в этом отношении) вы никогда не разыменовываете указатель NULL. Такое поведение имеет неопределенное поведение (вероятно, это ошибка в любой реализации, о которой я знаю, но все может произойти в соответствии со стандартом). Наверное, это плохо на других языках, но я не знаю, достаточно ли этого, чтобы утверждать это.
Лучше предотвратить ситуацию, чем пытаться восстановиться после нее (что в любом случае невозможно сделать на C или C++).
Обычная схема предотвращения некоторых связанных ошибок программиста заключается в использовании assert()
внутри функциональных органов, таких как:
int foo(int* myint)
{
// Ensure myint is not NULL
assert(myint);
// Do something with myint
(*myint)++;
return *myint;
}
такие assert()
вызовы полностью игнорируются при сборке релизов и, следовательно, не требуют затрат при производстве. Они просто помогают развитию. При отладочных сборках, и если условие не выполняется, программа немедленно прерывается с очень явным сообщением об ошибке. Запустив его через отладчик, вы можете легко проверить стек вызовов, чтобы выяснить точную причину.
В C++ нет стандартного исключения для разыменования пустого указателя.
Если вы хотите, вы можете реализовать это самостоятельно. В UNIX установите обработчик сигнала SIGSEGV и сгенерируйте исключение из обработчика. В Windows используйте API _set_se_translator () для установки обработчика "Структурное исключение".
Почти во всех случаях, когда неправильно используется нулевой указатель (особенно разыменование), стандарт C++ просто оставляет поведение неопределенным. Для конкретного типа исключения не предусмотрено (и исключение не будет выдано).
Однако на ум приходит одно возможное исключение из этого правила. std::function
, который является шаблоном стандартной библиотеки C++11, который может использоваться для переноса функций, может быть назначен нулевой указатель:
std::function<void(int)> func = nullptr;
И если вы затем попытаетесь вызвать обернутую ею функцию, выполнив func(arg);
для некоторого аргумента arg
Кидает std::bad_function_call
исключение.
Это, конечно, не полностью эквивалентно исключениям нулевого указателя в других языках, потому что оно гораздо менее применимо.
FTR, в C# вы не используете NullReferenceException
за что угодно, если только вы не хотите получить удар от своих товарищей по команде. E сть ArgumentNullException
вместо того, чтобы отклонить нулевые аргументы. NRE предназначены для запуска во время выполнения, а не для вас.
Но обратите внимание, что на самом деле это не преимущество перед утверждением, потому что вы не должны ловить один из них: если они выброшены, они указывают на ошибку. Это то, что Эрик Липперт называет исключениями с тупой головой, и это ваша собственная ошибка, и ваш код ничего не должен делать именно с ними.
В C++ разыменование нулевого указателя приведет к неопределенному поведению, что в основном завершает приложение ошибкой сегментации. В Visual Studio вы можете использовать такие расширения, как Структурная обработка исключений (SEH), которые позволяют перехватывать нулевой указатель.
Вы можете обернуть указатель в шаблонный класс, который предоставляет ограниченный интерфейс для указателя. Он может выполнять проверку nullptr всякий раз, когда вы обращаетесь к указателю, и генерировать исключение.