假设我有一个C库,我使用Visual Studio链接到Windows上的C ++程序。这个C库是黑盒子。如果此库中发生致命错误(例如取消引用null),程序/ OS将如何处理此运行时错误?我在C ++中知道存在空引用异常,因此您可以使用try / catch处理此类错误,但由于这是一个C库,它不会发出throw
,对吧?那会发生什么?该程序将终止,但通过什么方式,如果不是C ++异常?
答案 0 :(得分:6)
您永远不能“处理”取消引用空指针。执行此操作后,您的程序将不再处于定义良好的状态,并且无法确定性地继续执行。唯一的操作方法是terminate()
,如果您没有注册SIGSEGV处理程序,操作系统将代表您进行操作。
“错误”这个词有几个含义可能令人困惑:一方面,一个无法执行其预期任务的功能可能被称为遇到了“错误”,并且可能会发出信号这可以通过合适的返回值,也可以通过抛出异常来实现。此行为最好称为失败。必须准备一个正确的程序来处理函数可能返回的所有可能方式。另一方面,存在编程错误,这只会导致错误甚至形成错误的程序。正确的程序绝不能有任何编程错误。
例如,malloc()
可能失败(如果找不到足够的空间),它通过返回空指针发出信号,但如果取消引用结果,则程序将出错malloc()
没有检查。
通过进一步编程,您永远不会“捕获”或“处理”编程错误。相反,正确的程序必须正确地预测和处理组件函数的所有失败条件,并且递归地正确编写的函数必须始终以明确定义的方式返回并且适当地发出信号失败。
答案 1 :(得分:4)
在本机代码中取消引用空指针将导致Windows上的“访问冲突”或Unix / Linux上的“分段错误”。同一件事的不同名称。它是检测错误的CPU,它调用操作系统中的处理程序,终止进程。
在基于VM的语言(例如.NET或Java)中取消引用空引用将引发您可以捕获的异常。这是可能的,因为VM位于程序和CPU之间,它可以在尝试实际取消引用它之前检测到null。
C库是本机代码,因此您将获得访问冲突。您可以从真正的C ++程序中获得相同的结果,该程序也可以编译为本机代码。但是,如果您使用的是托管C ++或C ++ / CLI,则这些变体可以编译为CIL并在.NET运行时运行,因此在这种情况下会出现NullReferenceException。
答案 2 :(得分:2)
支持使用C ++ catch
关键字捕获的“异步”或“结构化”异常(例如无效的内存访问)是C ++语言的MSVC扩展。
只要您使用正确的编译器选项/EHa
__try
您还可以选择使用Microsoft的“结构化异常”处理语言扩展(也可在C中使用),该扩展使用__except
和{{1}}个关键字:http://msdn.microsoft.com/en-us/library/1deeycx5%28v=VS.100%29.aspx