作为开发者,假如我违反了所使用库的某个前条件,我不希望栈展开。我希望的是core dump或者等价物—一个能精确地在问题发生点检查程序状态的方法。这通常意味着assert()或者其他类似的东西。
有时候为用户提供可以应付任意误用的强健的API是有必要的,但这样通常要付出不菲的代价。比如,一个常见需求是跟踪客户使用的每一个对象,从而可以验证合法性。假如你需要这种保护,通常是在一个简单API上再封装一层来实现。尽管你做得小心翼翼,有强健承诺的API也只能防御某些而不是所有会导致灾难的误用。客户也开始依靠那些保护并且所依靠的保护也将增长到接口保护不到的部分。
windows开发者请注重:当你使用assert()时,大部分Windows编译器实际上都是抛出异常,并且被本地截获,这很不幸。事实上,截获的错误经常是段访问失败或者除零错。当你使用JIT(Just In Time)调试时这是个问题,这意味着在在唤醒调试器之前已经异常栈展开了,因为catch(…)将捕捉这个异常,其实这个并非C++异常。幸运的是,有一个鲜为人知的简单办法可以处理:
extern "C" void straight_to_debugger(unsigned int, EXCEPTION_POINTERS*)
{
throw;
}
extern "C" void (*old_translator)(unsigned, EXCEPTION_POINTERS*)= _set_se_translator(straight_to_debugger);
这个方法无法应付在catch块中(或者catch块调用的函数中)抛出结构化异常的情况,但它确实可以解决绝大多数JIT导致的问题。