如何捕获空指针exception?
try { int* p = 0; *p = 1; } catch (...) { cout << "null pointer." << endl; }
我试图捕捉这样的exception,但它不工作,有任何帮助?
在C ++中没有“空指针exception”这样的事情。 唯一可以捕捉的例外是throw
expression式显式抛出的exception(另外,正如Pavel指出的那样,标准operator new
, dynamic_cast
等本质上抛出了一些标准的C ++exception)。 在C ++中没有其他例外。 解引用空指针,除零等不会在C ++中产生exception,它会产生未定义的行为 。 如果你想在这样的情况下抛出exception,你自己有责任手动检测这些条件并明确地throw
。 这就是它在C ++中的工作原理。
无论你在寻找什么,都与C ++语言有关,而是具体的实现。 例如,在Visual C ++中,系统/硬件exception可以被“转换”成C ++exception,但是这个非标准function附带了一个价格,这通常是不值得的。
你不能。 去引用空指针是一个系统的事情。
在Linux上,操作系统会在应用程序中产生信号。 看看csignal ,看看如何处理信号。 为了“捕捉”一个,你会钩一个函数,在SIGSEGV
的情况下将被调用。 在这里,您可以尝试打印一些信息,然后正常结束程序。
Windows使用结构化exception处理 。 你可以使用instristics __try/__except
前面的链接所述。 我在一个特定的debugging实用程序中编写的方法是使用_set_se_translator
函数(因为它非常匹配钩子)。 在Visual Studio中,确保启用了SEH。 使用这个函数,当系统在应用程序中引发一个exception时,可以挂钩一个函数来调用; 在你的情况下,它会用EXCEPTION_ACCESS_VIOLATION
调用它。 然后你可以抛出一个exception,并把它传播回来,就好像抛出exception一样。
解引用null(或指向数组结尾的指针或随机无效指针)会导致未定义的行为。 没有便携的方法来“捕捉”。
在Visual Studio中使用try
– > catch (...)
块捕获任何types的exception(除以零,访问冲突等)是非常简单的方法。
一个小的项目调整就足够了。 只需在项目设置中启用/EHa
选项。 请参阅项目属性 – > C / C ++ – >代码生成 – >将启用C ++exception修改为“是有SEHexception” 。 而已!
在此处查看详细信息: http : //msdn.microsoft.com/en-us/library/1deeycx5(v=vs.80).aspx
C + +不会做指针检查(虽然我想有些实现可能)。 如果你试图写一个空指针,它很可能会很难崩溃。 它不会抛出exception。 如果你想知道这一点,你需要在写入指针前自己检查一下指针的值。
一般你不能。 即使你可以这样做,就好像试图将一个乐队的援助物放在已经发生泄漏的潜艇上。
一个残缺的应用程序可能会比已经崩溃的应用程序造成更大的损失。 我的build议是让它崩溃然后解决它为什么崩溃。 冲洗。 重复。
正如其他人所说,你不能在C ++中做到这一点。
如果我能够提出一个更广泛的观点:即使用一种能让你抓住它的语言,最好的办法就是不要碰空指针。 当它已经被炸毁的时候发现一个错误,然后决定继续前进,这不是一个好的编码策略。 像空指针解引用,堆栈溢出等等,应该被视为灾难性的事件,并且在防御上避免,即使你的语言允许你对它作出不同的反应。
没有平台独立的方式来做到这一点。 在Windows / MSVC ++下,您可以使用__try / __除外
但我不会推荐这样做。 你几乎肯定不能从分段错误中正确地恢复。
如果你想要你可以做指针检查你自己并抛出…
if (p == nullptr) throw std::exception("woot! a nullptr!") p->foo();
所以当然这只会是debugging的问题,nullptr不应该发生在第一个地方:)
简短的回答 – 你不能以便携或标准的方式,因为这样的错误可能会破坏过程本身。
长的答案 – 你可以做的比你想象的要多,而且肯定比刚刚崩溃的程序的默认值要多。 但是,你需要记住3件事情:
1)这些错误比例外更严重,往往不能作为你的逻辑的例外。
2)即使您可以提供一个干净的抽象界面供公众使用,您的检测和库的处理将依赖于平台的后端。
3)总会有一些崩溃是非常糟糕的,你甚至不能在结束之前检测到它们。
基本上,像段错误或堆腐败的故障不是例外,因为它们正在破坏运行程序的实际进程。 你编入程序的任何东西都是程序的一部分,包括exception处理,所以除了在进程死亡之前logging一个好的错误消息之外的任何东西都是不可取的,在less数情况下,这不是不可能的。 在POSIX中,操作系统使用信号系统来报告类似的故障,并且可以注册callback函数来logging退出之前的错误。 在Windows中,操作系统有时可以将它们转换为正常的exception,您可以捕获并从中恢复。
但是,最终你最好的办法就是防守编码,防止这样的噩梦。 在任何给定的操作系统上都会有一些非常糟糕的东西,即使在原理上,在你的进程死亡之前,你也无法检测到它们。 例如,破坏自己的堆栈指针可能会使你非常糟糕,即使你的POSIX信号callback也不会看到它。
在VC ++ 2013(以及更早版本)中,您可以将例外的断点:
- 按下Ctrl + Alt + Delete(这将打开exception对话框)。
- 展开“Win32例外”
- 确保选中“0xC0000005访问冲突”exception。
现在再次debugging,一个断点将被精确打到空的解除引用发生。
在c ++中不存在NULL指针exception,但是你仍然想要捕获它,那么你需要提供相同的类实现。
下面是同样的例子。
class Exception { public: Exception(const string& msg,int val) : msg_(msg),e(val) {} ~Exception( ) {} string getMessage( ) const {return(msg_);} int what(){ return e;} private: string msg_; int e; };
现在基于NULL指针检查它可以像扔, throw(Exception("NullPointerException",NULL));
下面是捕捉相同的代码。
catch(Exception& e) { cout << "Not a valid object: " << e.getMessage( )<< ": "; cout<<"value="<<e.what()<< endl; }