【问题标题】:What's better to use, a __try/__except block or a try / catch block?__try/__except 块还是 try/catch 块更好用?
【发布时间】:2011-04-13 10:32:23
【问题描述】:

我想知道捕获我抛出的异常的更好方法是:它是 __try / __except 块还是 try / catch 块?

我是用 C++ 编写的,该程序只能在 Windows 上使用,所以可移植性不是问题。

谢谢!

【问题讨论】:

    标签: c++ c performance exception try-catch


    【解决方案1】:

    它们是两个非常不同的东西。 try/catch 是您熟悉的 C++ 关键字。 __try/__except 用于捕获 SEH 异常。 Windows 本身引发的异常,例如 DivisionByZero 或 AccessViolation。在MSDN Library article 中对此进行了很好的描述。

    您还可以使用它来捕获 C++ 异常,因为它利用了 Windows SEH 功能。但是,您无法从中获取抛出的异常对象,因此如果您确实想要处理异常,则上下文为零。这是疯狂。第一种方法是永远不要捕获 SEH 异常,它们总是很严重。如果您确实需要将两者结合起来,请使用 _set_se_translator() 将 SEH 异常转换为 C++ 异常。

    【讨论】:

      【解决方案2】:

      __try/__except 设计用于调用不支持异常但使用结构化错误代码/处理机制的 Win32 C 代码。 __try/__except 会将 C 错误转换为与 C++ try/catch 相似 的异常块。

      有关详细信息,请参阅this MSDN article

      【讨论】:

        【解决方案3】:

        标准 C++ 使用 try/catch 块,所以如果您需要基于标准 C++ 库的“标准”异常机制,我建议使用它们。

        但是,如果您计划使用通过 Windows SDK 提供的结构化异常处理(请参阅here),请使用__try/__except

        【讨论】:

        • -1:STL 与异常处理完全无关。
        • STL 绝对与异常处理有关:std::exception,这是推荐的异常基类,即使它不是强制性的。
        • std::exception 不是 STL 类。
        • 对不起。标准 C++ 库更好用吗?
        • @Cătălin Pitiş:是的,那会更好,但仍然不会相当迂腐:)(在修改后我会删除我的反对票)
        【解决方案4】:

        您应该使用try/catch 块。

        正如其他人已经回答的那样,__try / __except 用于捕获 SEH(Windows 生成的错误),而不是用于捕获一般异常。

        最重要的是,__try__catch 在抛出异常时可能无法运行 C++ 析构函数或正确展开堆栈。

        除非在极少数情况下,否则永远不要尝试捕获 SEH 异常。

        编辑:好吧,我对此持肯定态度(这是我一直被告知的),但@Hans 说显然有一个编译器开关可以用来改变它。我认为/EHa 上的文档对这里发生的事情具有误导性,或者至少是不完整的。如果有人找到证明此错误的权威文档,我会很乐意删除此答案。

        即使事实证明这是错误的,您仍然应该使用 trycatch,因为它们是标准的,而 __try__except 不是。

        【讨论】:

        • @David:没错。 __try__except 严格来说是基于 C 的 API/ABI。
        • 这不准确。使用 /EHa 编译可确保在堆栈展开期间调用 C++ 析构函数。
        • @Hans:你能找到这方面的文档吗?我对/EHa 的理解仅仅是它允许C++ 异常处理构造(当您使用trycatch 时)捕获SEH 异常,但是当__try__except 时C++ 堆栈仍然没有正确展开被使用。
        • 只有 /EH 文档。是的,这不是很好。 /EHa 抑制编译器优化,当编译器检测到没有任何发出的代码可以引发 C++ 异常时,忽略异常清理处理程序。当你查看机器代码时,你可以看到它们。
        • @Alex: __except 可以捕获 C++ 异常;但我的理解是,这样做时不能保证提供 C++ 堆栈展开语义。除非,正如 Hans 所说,在/EHa 下。 (请不要使用/EHa
        【解决方案5】:

        一旦你扔了东西,你就再也没有太多选择来抓住它了。如果您抛出 C++ 异常(即使用throw),则使用try/catch。如果您抛出 Windows 异常(即使用RaiseException),则使用__try/__except。试图混合它们只会给你的生活增加不必要的麻烦。

        【讨论】:

        • 但是你不应该抛出 windows 异常,因为它们不会展开堆栈。
        • @BillyONeal 显然是在 windows10 之前设置线程名称的唯一方法:docs.microsoft.com/en-us/visualstudio/debugger/…
        • 在这种情况下,堆栈展开是无关紧要的,@chacham,因为你只是为了引起调试器的注意,而不是为了改变程序的流程。您立即捕获并丢弃异常。不过,重点仍然是,对于如何 捕获该异常,您没有真正的选择。你用RaiseException扔它,所以你必须用__except抓住它。
        • 当然,但是“但你永远不应该抛出 windows 异常”并不完全准确。
        猜你喜欢
        • 2012-02-07
        • 2011-10-26
        • 2016-08-26
        • 2016-05-21
        • 1970-01-01
        • 1970-01-01
        • 2019-12-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多