抛出意外异常时,为什么此程序不会中止?

时间:2015-07-15 05:45:48

标签: c++ exception abort

我正在经历 $q = "SELECT * FROM `curriculum` " . "INNER JOIN `subject` ON `curriculum`.`subject`=`subject`.`sub_id` " . "LEFT JOIN `subject` ON `curriculum`.`cur_pr`=`subject`.`sub_id` " . "WHERE `course`=:cid and `cur_year`=1";

在那里,提到如果我们从其签名指定一组预定义异常类型的函数抛出意外异常,则应该调用C++ FAQ 2nd Edition, FAQ 9.04- What is an exception specification?。 但是我的程序捕获了意外的异常而不是unexpected()->terminate()->abort(),为什么?

abort()

这里我得到的输出#include<iostream> using namespace std; class Type1{}; class Type2{}; class Type3{}; void func() throw(Type1, Type2) { throw Type3(); } int main() { try{ func(); } catch (Type1 &obj1) { cout << "Type1 is caught" << endl; } catch (Type2 &obj2) { cout << "Type2 is caught" << endl; } catch (Type3 &obj3) { cout << "Type3 is caught" << endl; } } 不应该出现。

IDE:VS2013

3 个答案:

答案 0 :(得分:6)

正如Adriano Repetti所说,MSVC会忽略异常规范。但是有一些原因。

来自SO的other post解释说,异常规范解释了编译器不能将异常控制强制为编译时,并且必须生成代码才能在运行时控制它。这就是编译器(特别是MSVC)支持不足的原因。

它引用了GOTW的一篇非常详细的文章,结论是:

所以这就是我们社区今天所学到的最佳建议:

  • 道德#1:永远不要编写例外规范。
  • 道德#2:除了可能是空的,但如果我是你,我甚至会避免。

答案 1 :(得分:4)

来自MSDN:

  

解析了throw()以外的函数异常说明符但未使用。这不符合ISO C ++规范的第15.4节

Visual C ++根本不遵循标准(引自Mohit's answer中的标准)。

编辑:关于子问题“为什么不呢?”我试着从评论中总结一下所说的内容。

  • 首先,商业编译器始终面临成本/收益比率。如果实现某项功能(直接或间接)的成本(直接或间接)超过其价值(直接或间接),则很有可能无法实施(至少很快)。在我看来,这是一个重要的考虑因素, small 功能可能会影响编译器的复杂性和性能(也可以阅读关于此主题的许多Eric Lippert C#帖子中的一篇)。
  • 实现某项功能可能会对性能产生很大影响(在这种情况下,这似乎是原因,请参阅Serge's answer)。
  • 某些规格不清楚和/或有问题。另请参阅What's the point of nested classes?
  • 更改某些内容可能会破坏现有代码。这些重大变化总是需要认真考虑(特别是如果它们在编译时没有破坏任何东西,而是在运行时)。什么时候可能发生?例如:
    • 编译器引入了语言扩展,后来在未来的标准中断言了不同的内容。
    • 规格不明确,或者他们留下了具体实施细节。
    • 规范实施中的编译器错误已经很好地建立。例如,当Microsoft重写C#编译器时,Roslyin实现必须重现旧编译器中的错误。另请参阅SLaks' blog有关重大更改的信息(他们没有为所有内容执行此操作)。
  • 某些功能(如本例所示)对您的代码在商业实现之前几乎没有什么价值(例如,不要忘记MSVC ++的更新频率低于GCC),他们已被弃用那么就没有必要支持他们了。

答案 2 :(得分:1)

来自except_spec

  

如果函数抛出了未在其中列出的类型的异常   异常规范,调用函数std :: unexpected。

所以看来VS2013不符合本节的要求。