这是一个不寻常的问题,但请注意:
在我的代码中,我意外地在某处取消引用NULL。但是,不是使用segfault崩溃的应用程序,它似乎停止执行当前函数并将控制权返回给UI。这使得调试变得困难,因为我通常希望收到崩溃警报,以便我可以附加调试器。
导致这种情况的原因是什么?
具体来说,我的代码是ODBC驱动程序(即DLL)。我的测试应用程序是ODBC测试(odbct32w.exe),它允许我在我的DLL中显式调用ODBC API函数。当我调用其中一个已知段错误的函数时,ODBC测试只是将控制权返回给UI而不打印函数调用的结果。然后我可以再次调用我的驱动程序中的任何函数。
我确实知道技术上应用程序调用ODBC驱动程序管理器来加载和调用驱动程序中的函数。但是,由于我的段错误(或正在发生的任何事情)导致驱动程序管理器函数也没有返回(正如应用程序未打印结果所证明的那样),这就是重点。
我的一个拥有类似机器的同事遇到了同样的问题而另一个没有,但我们无法确定任何具体的差异。
答案 0 :(得分:42)
Windows有non-portable language extensions (known as "SEH"),可以将页面错误和分段违规作为例外进行捕获。
有一些OS库的部分(特别是在OS代码中处理一些窗口消息,如果我没记错的话)有一个__try
块,并且即使面对这样的代码也会让你的代码继续运行灾难性的错误。可能你被称为这些__try
块中的一个。悲伤却又是真的。
查看此博文,例如:The case of the disappearing OnLoad exception – user-mode callback exceptions in x64
更新
我觉得在评论中归咎于我的那种想法有点奇怪。记录:
我不声称SEH本身不好。
我说这是“非便携式”,这是事实。我还声称使用SEH忽略用户模式代码中的STATUS_ACCESS_VIOLATION
是“悲伤”。我支持这个。我希望我有勇气在新代码中执行此操作,并且您正在查看我会对我大喊大叫的代码,就像我写了catch (...) { /* Ignore this! */ }
一样。这是个坏主意。这对于访问冲突尤其不利,因为获取AV通常意味着您的进程处于错误状态,并且您不应该继续执行。
我做了不认为SEH的存在意味着你必须吞下所有的错误。
当然SEH是一个通用机制,不应该归咎于每一个愚蠢的使用它。我所说的是一些Windows二进制文件在调用函数指针时吞下STATUS_ACCESS_VIOLATION
,这是一个真实且可观察的事实,并且这不是很漂亮。请注意,他们可能有历史原因或情有可原的情况来证明这一点。因此“伤心但真实。”
我做了不在这里注入任何“Windows vs. Unix”的修辞。在任何平台上,一个坏主意都是个坏主意。尝试在Unix类型操作系统上从SIGSEGV
恢复也同样粗略。
答案 1 :(得分:18)
取消引用NULL指针是一种未定义的行为,它几乎可以产生任何东西 - 一个seg.fault,一封写入IRS的信,或一个发布到stackoverflow的帖子:)
答案 2 :(得分:2)
了解不同类型的异常处理程序here - 它们没有捕获相同类型的异常。
答案 3 :(得分:2)
Windows 7也有其容错堆(FTH),它有时会做这些事情。在我的情况下,它也是一个NULL-dereference。如果你在Windows 7上开发,你真的想要关闭它!
What is Windows 7's Fault Tolerant Heap?
http://msdn.microsoft.com/en-us/library/dd744764%28v=vs.85%29.aspx
答案 4 :(得分:1)
将您的调试器附加到可能调用您的dll的所有应用程序,在[debug] | [exceptions]菜单中不仅处理错误时启用该功能以打破该功能。
ODBC是大多数(如果不是全部)COM,因为这样的未处理异常会导致问题,这些问题可能看起来像是奇怪地退出ODBC函数,或者因为它挂起而永远不会返回。