从失败终止到崩溃
一个失败的终止
撞车事故时有发生。任何比“Hello world”更复杂的程序都可能有一些bug。专业软件开发的一个衡量标准是如何处理这些崩溃。程序应该保存一个崩溃转储,然后自杀(TerminateProcess()或_exit(),而不是ExitProcess()或exit())。
你不想让这个注定要失败的进程弹出一个对话框,说“嘿,我是一个注定要失败的进程”。但不幸的是,这是VisualC++C运行时间(VC++)在某些情况下所做的,正如我们看到的那样。
如果您不小心调用了一个纯虚拟函数,则此处理程序将打开一个对话框。如果你是一个开发人员,那么你可以附加一个调试器并获得一个调用堆栈,但世界上大多数人都不是开发人员。他们不知道什么是纯虚函数调用,也不在乎。显示此对话框只会减慢崩溃恢复过程,同时让用户感到困惑。
但更糟糕的是。如果你有一群异常处理程序准备捕捉Win32异常(访问冲突等),那么你会失望的,因为他们不会捕捉到纯粹的调用错误,即使有人按了OK。所以,你的内部崩溃转储记录系统对这个错误无能为力,这意味着它需要更长的时间来修复。
更更糟糕的是,如果这个错误发生在服务器上(我见过),那么您的无头服务器现在有一个挂起的进程正在等待某人单击“确定”。单元测试最终会超时,如果您有看门狗,服务器可能会超时,但是整个过程会被这个对话框延迟。
除非我能提供解决方案,否则我不会写这篇文章。上面的对话框是默认行为,但是一旦您知道应该更改默认值,就很容易了。您所要做的就是使用一个故意崩溃的函数调用_set_purecall_handler()。我最喜欢的实现是在TerminateProcess()后面执行一个_debugbreak()。如果我在调试器下运行,这会很好地将我放入其中,如果我不是,那么我未处理的异常过滤器将捕捉异常并写出一个小转储。TerminateProcess()用于阻止在调试器中捕获异常的用户尝试继续。
无效参数在技术上不是崩溃
VC++CRT检测到CRT函数的一些无效参数,并将它们视为致命错误。如果您使用更安全的CRT函数(并且您没有请求截断),这包括缓冲区溢出检测,但是触发这些检查的最简单方法是使用“printf(NULL);”。
不会弹出任何对话框(至少在发布版本中没有),并且进程被终止,但不会通过调用精心编制的异常处理程序来终止。Windows错误报告(WER)会收到问题的通知,这很好,但我希望这些无效参数像崩溃一样处理,以便调用异常处理程序。幸运的是,这个问题也有一个简单的解决方案。如果调用_set_invalid_parameter_handler(),则可以为它提供与纯调用处理程序相同的代码(只是带有不同的签名),以便异常处理程序注意到发生了错误。现在你的程序会比以前更糟糕。这是件好事。示例代码中也演示了这种技术。
WER是你的朋友
Windows错误报告(WER)是Windows内置的一个方便的功能。大多数开发人员都知道WER会在数百万用户的计算机上记录崩溃转储并将其存储起来,而且大多数开发人员也知道可以访问您的软件的崩溃转储。这是一个很好的方法,可以找出你的软件在实际客户的实际机器上实际崩溃的地方。虽然有一些困难需要克服,但还是值得一试的。不过,我不知道如何安排这样的访问,所以我就不多说了。
缩减Windbg的子窗口
Windbg偶尔会自动缩减新开的窗口,这有时会让我们烦恼。如果你想回到默认窗口布局,可以通过如下操作:
菜单File\Delete Workspace删除被调试进程所保持的工作区
如果你不满意所有会话窗口布局,但又不无法直接关闭程序,可以手动删除如下注册表项后重启Windbg:
USER\Software\Microsoft\Windbg\Workspaces
上面说的方法都会删除工作区其他数据。
windbg如何让.cmdtree自动执行?
.cmdtree命令(WinDbg常用命令系列---.cmdtree)的功能给我们带来了方便,但在使用中,你会发现每当退出调试后,在启动调试,还得必须执行一次.cmdtree命令。这其实也有点繁琐。
这个问题其实很好解决,通过设置windbg快捷方式属性即可:
关于STATUS_FLOAT_MULTIPLE_TRAPS(0xC00002B5)异常
简介
STATUS_FLOAT_MULTIPLE_TRAPS---浮点数多重陷阱异常。值为0xC00002B5。定义如下
//
// MessageId: STATUS_FLOAT_MULTIPLE_TRAPS
//
// MessageText:
//
// {EXCEPTION}
// Multiple floating point traps.
//
#define STATUS_FLOAT_MULTIPLE_TRAPS ((NTSTATUS)0xC00002B5L) // winnt
说明
当进行浮点数运算时,且设置了浮点异常模式,当遇到比如除0.0操作时,抛此异常。
异常结构说明
ExceptionAddress: 00f515dc
ExceptionCode: c00002b5
ExceptionFlags: 00000000
NumberParameters: 2
Parameter[0]: 00000000
Parameter[1]: 0000e144---浮点 MXCSR寄存器的值,包含设置的浮点异常掩码、当前异常状态值、清零模式和四舍五入模式等
关于STATUS_FLOAT_MULTIPLE_FAULTS(0xC00002B4)异常
简介
STATUS_FLOAT_MULTIPLE_FAULTS---多浮点错误。值为0xC00002B4。定义如下
//
// MessageId: STATUS_FLOAT_MULTIPLE_FAULTS
//
// MessageText:
//
// {EXCEPTION}
// Multiple floating point faults.
//
#define STATUS_FLOAT_MULTIPLE_FAULTS ((NTSTATUS)0xC00002B4L) // winnt
说明
当进行浮点数运算时,且设置了浮点异常模式,当遇到溢出时,抛此异常。
异常结构说明
ExceptionAddress: 0091146f (ConsoleApplication2!_Pow_int<double>+0x0000005f)
ExceptionCode: c00002b4
ExceptionFlags: 00000000
NumberParameters: 2
Parameter[0]: 00000000
Parameter[1]: 00001ba8----浮点 MXCSR寄存器的值,包含设置的浮点异常掩码、当前异常状态值、清零模式和四舍五入模式等