C++ 如何捕获空指针异常?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1823721/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to catch the null pointer exception?
提问by mindhacks
try {
int* p = 0;
*p = 1;
} catch (...) {
cout << "null pointer." << endl;
}
I tried to catch the exception like this but it doesn't work,any help?
我试图捕捉这样的异常,但它不起作用,有什么帮助吗?
回答by AnT
There's no such thing as "null pointer exception" in C++. The only exceptions you can catch, is the exceptions explicitly thrown by throw
expressions (plus, as Pavel noted, some standard C++ exceptions thrown intrinsically by standard operator new
, dynamic_cast
etc). There are no other exceptions in C++. Dereferencing null pointers, division by zero etc. does not generate exceptions in C++, it produces undefined behavior. If you want exceptions thrown in cases like that it is your own responsibility to manually detect these conditions and do throw
explicitly. That's how it works in C++.
C++ 中没有“空指针异常”这样的东西。您可以捕获的唯一异常是throw
表达式显式抛出的异常(另外,正如 Pavel 所指出的,一些标准 C++ 异常由 standard 本质上抛出operator new
,dynamic_cast
等等)。C++ 中没有其他例外。取消引用空指针、除以零等不会在 C++ 中产生异常,它会产生未定义的行为。如果您希望在这种情况下抛出异常,您有责任手动检测这些条件并throw
明确执行。这就是它在 C++ 中的工作方式。
Whatever else you seem to be looking for has noting to do with C++ language, but rather a feature of particular implementation. In Visual C++, for example, system/hardware exceptions can be "converted" into C++ exceptions, but there's a price attached to this non-standard functionality, which is not normally worth paying.
您似乎正在寻找的其他任何东西都与 C++ 语言无关,而是特定实现的功能。例如,在 Visual C++ 中,系统/硬件异常可以“转换”为 C++ 异常,但是这种非标准功能需要付出代价,通常不值得付出代价。
回答by GManNickG
You cannot. De-referencing a null-pointer is a system thing.
你不能。取消引用空指针是系统的事情。
On Linux, the OS raises signals in your application. Take a look at csignalto see how to handle signals. To "catch" one, you'd hook a function in that will be called in the case of SIGSEGV
. Here you could try to print some information before you gracefully terminate the program.
在 Linux 上,操作系统会在您的应用程序中发出信号。查看csignal以了解如何处理信号。要“捕获”一个,您需要挂钩一个函数,该函数将在SIGSEGV
. 在这里,您可以尝试在正常终止程序之前打印一些信息。
Windows uses structured-exception-handling. You could use the instristics __try/__except
, as outlined in the previous link. The way I did it in a certain debug utility I wrote was with the function _set_se_translator
(because it closely matches hooks). In Visual Studio, make sure you have SEH enabled. With that function, you can hook in a function to call when the system raises an exception in your application; in your case it would call it with EXCEPTION_ACCESS_VIOLATION
. You can then throw an exception and have it propagate back out as if an exception was thrown in the first place.
Windows 使用结构化异常处理。您可以使用 instristics __try/__except
,如上一个链接中所述。我在我编写的某个调试实用程序中的方法是使用函数_set_se_translator
(因为它与钩子非常匹配)。在 Visual Studio 中,确保已启用 SEH。使用该函数,您可以挂钩一个函数以在系统在您的应用程序中引发异常时调用;在你的情况下,它会用EXCEPTION_ACCESS_VIOLATION
. 然后,您可以抛出异常并将其传播回原处,就像首先抛出异常一样。
回答by Pavel Minaev
Dereferencing a null (or pointer that's past-the-end of array, or a random invalid pointer) results in undefined behavior. There's no portable way to "catch" that.
取消引用空值(或数组末尾的指针,或随机无效指针)会导致未定义的行为。没有可移植的方法来“捕捉”它。
回答by Volodymyr Frytskyy
There is a very easy way to catch any kind of exception (division by zero, access violation, etc.) in Visual Studiousing try
-> catch (...)
blocks.
有一种非常简单的方法可以使用->块在Visual Studio 中捕获任何类型的异常(被零除、访问冲突等)。try
catch (...)
A minor project tweaking is enough. Just enable the /EHa
option in project settings. See Project Properties -> C/C++ -> Code Generation -> Modify the Enable C++ Exceptions to "Yes With SEH Exceptions". That's it!
一个小的项目调整就足够了。只需/EHa
在项目设置中启用该选项即可。请参阅项目属性 -> C/C++ -> 代码生成 -> 将 Enable C++ Exceptions 修改为“Yes With SEH Exceptions”。就是这样!
See details here: http://msdn.microsoft.com/en-us/library/1deeycx5(v=vs.80).aspx
在此处查看详细信息:http: //msdn.microsoft.com/en-us/library/1deeycx5(v=vs.80).aspx
回答by Nate C-K
C++ doesn't do pointer checking (although I suppose some implementations could). If you try to write to a null pointer it is most likely going to crash hard. It will not throw an exception. If you want to catch this you need to check the value of the pointer yourself before you try to write to it.
C++ 不进行指针检查(尽管我认为某些实现可以)。如果您尝试写入空指针,它很可能会严重崩溃。它不会抛出异常。如果你想抓住这个,你需要在尝试写入之前自己检查指针的值。
回答by 0xC0DEFACE
Generally you can't. Even if you could it would be like trying to put a band aid on a submarine that has sprung a leak.
一般你不能。即使你能做到,这就像试图在发生泄漏的潜艇上贴上创可贴。
A crippled application can do far more damage than one that has crashed. My advice here would be to let it crash then fix why it crashed. Rinse. Repeat.
一个瘫痪的应用程序可能比崩溃的应用程序造成更大的损害。我的建议是让它崩溃然后修复它崩溃的原因。冲洗。重复。
回答by asveikau
As others have said, you can't do this in C++.
正如其他人所说,你不能在 C++ 中做到这一点。
If I can make a broader point: even in a language that allows you to catch it, the better action is to not touch null pointers. Catching an error when it's already blown up in your face, then deciding to just move on like it didn't happen, is not a good coding strategy. Things like null pointer dereference, stack overflow, etc., should be seen as catastrophic events and defensively avoided, even if your language allows you to react to it differently.
如果我能提出一个更广泛的观点:即使在允许您捕捉它的语言中,更好的行动是不要触摸空指针。当它已经在你面前炸毁时发现错误,然后决定继续前进,就像它没有发生一样,不是一个好的编码策略。像空指针取消引用、堆栈溢出等,应该被视为灾难性事件并防御性地避免,即使您的语言允许您对它做出不同的反应。
回答by Axel Gneiting
回答by Jan Wilmans
If you wanted to you could just do the pointer checking yourself and throw...
如果你愿意,你可以自己检查指针并抛出......
if (p == nullptr) throw std::exception("woot! a nullptr!")
p->foo();
so course this would only be to debug the problem, the nullptr should not occur in the first place :)
所以当然这只是为了调试问题,首先不应该出现 nullptr :)
回答by Zack Yezek
Short answer- you can't in a portable or standard way, because bugs like this are potentially corrupting the process itself.
简短的回答——你不能以便携或标准的方式,因为像这样的错误可能会破坏进程本身。
Long answer- you can do more than you might think, and definitely more than the default of the program just crashing. However, you need to keep 3 things in mind:
1) These bugs are MORE severe than exceptions and often cannot present as exceptions to your logic.
2) Your detection and library handling of them WILL be platform-dependent on the back end, even though you can provide a clean abstract interface for public consumption.
3) There will always be some crashes that are so bad you cannot even detect them before the end.
长答案-您可以做的比您想象的要多,而且绝对不仅仅是程序崩溃的默认设置。但是,您需要记住 3 件事:
1) 这些错误比异常更严重,并且通常不能作为逻辑异常出现。
2)您对它们的检测和库处理将依赖于后端的平台,即使您可以为公共消费提供一个干净的抽象接口。
3)总会有一些非常糟糕的崩溃,你甚至无法在结束之前检测到它们。
Basically, faults like segfaults or heap corruption are not exceptions because they're corrupting the actual process running the program. Anything you coded into the program is part of the program, including exception handling, so anything beyond logging a nice error message before the process dies is inadvisable in the few cases it isn't impossible. In POSIX, the OS uses a signaling system to report faults like these, and you can register callback functions to log what the error was before you exit. In Windows, the OS can sometimes convert them into normal-looking exceptions which you can catch and recover from.
基本上,像段错误或堆损坏这样的错误并不是例外,因为它们会破坏运行程序的实际进程。您编码到程序中的任何内容都是程序的一部分,包括异常处理,因此在少数情况下,除了在进程终止之前记录一条好的错误消息之外的任何事情都是不可取的,这并非不可能。在 POSIX 中,操作系统使用信号系统来报告此类错误,您可以注册回调函数以在退出之前记录错误。在 Windows 中,操作系统有时可以将它们转换为外观正常的异常,您可以从中捕获和恢复。
Ultimately, however, your best bet is to code defensively against such nightmares. On any given OS there will be some that are so bad that you cannot detect them, even in principle, before your process dies. For example, corrupting your own stack pointer is something that can crash you so badly that even your POSIX signal callbacks never see it.
然而,最终,你最好的选择是防御性地编码以防止这种噩梦。在任何给定的操作系统上,都会有一些非常糟糕的,即使在原则上,在您的进程终止之前,您也无法检测到它们。例如,破坏您自己的堆栈指针会使您严重崩溃,甚至您的 POSIX 信号回调也无法看到它。