【问题标题】:Try catch is behaving wierd in C++Try catch 在 C++ 中的行为很奇怪
【发布时间】:2016-08-25 06:17:08
【问题描述】:

我正在学习示例,但我不是

#include <windows.h> // for EXCEPTION_ACCESS_VIOLATION

#include <excpt.h>

int filter(unsigned int code, struct _EXCEPTION_POINTERS *ep) {

    puts("in filter.");

    if (code == EXCEPTION_ACCESS_VIOLATION) {

        puts("caught AV as expected.");

        return EXCEPTION_EXECUTE_HANDLER;

    }

    else {

        puts("didn't catch AV, unexpected.");

        return EXCEPTION_CONTINUE_SEARCH;

    };

}

int main()

{

    int* p = 0x00000000;   // pointer to NULL

    puts("hello");

    __try {

        puts("in try");

        __try {

            puts("in try");

            *p = 13;    // causes an access violation exception;

        }
        __finally {

            puts("in finally. termination: ");

            puts(AbnormalTermination() ? "\tabnormal" : "\tnormal");

        }

    }
    __except (filter(GetExceptionCode(), GetExceptionInformation())) {

        puts("in except");

    }

    puts("world");

}

程序的输出是:

hello
in try
in try
in filter.
caught AV as expected.
in finally. termination:
        abnormal
in except
world

我很困惑为什么它会先过滤,然后再过滤,然后打印“in except”。 如果它转到 __except 是不是这样,它应该完成执行。

【问题讨论】:

  • 如果要求 c++ 代码,请使用 c++ 标准语法,否则在此处放置另一个标签。
  • 不确定是否可以在同一个函数中嵌套两个 __try。值得一试。
  • 谢谢你们.. 只是通过阅读 __try 定义我认为它与 try catch 类似
  • @Cheersandhth.-Alf 看起来像初学者的代码,但这个例子是从 MSDN 的文档中逐字复制的。
  • SEH 未尝试供应商锁定。操作系统需要一个与 C++ 没有任何关系的异常处理机制。一方面,C++ 异常还没有被发明出来。另一方面,操作系统不是用 C++ 编写的。第三,C++ 异常处理机制需要运行时支持,这显然需要操作系统或某人来编写代码。 Windows 使用 SEH。它比 C++ 规范定义的异常处理功能强大得多,并且可以捕获常规 try/catch 无法捕获的错误。 FUD 没有建设性。

标签: c++ winapi exception


【解决方案1】:

这些不是标准 C++ 例外,而是 Microsoft 自己的语言扩展。

如果您从找到该示例的页面继续阅读the documentation for try-finally,您会发现:

如果找到处理程序,则执行所有 __finally 块并在处理程序中继续执行。

这并不奇怪 - 在具有这些结构的语言中,总是会执行 finally 块(这就是它的目的)。
只是通常情况下,程序员无法在运行时控制异常在何处或是否被捕获,因此您不能像处理 filter 那样中断处理以查看幕后情况。

【讨论】:

  • 这正是我想要的
  • “即使 Microsoft 也建议您不要在 C++ 中使用这些。” - 对于无法使用 C++ 异常处理的情况,Microsoft 不建议使用 C++ 异常处理。具体来说,捕获访问冲突(例如,由于取消引用和写入nullptr)需要使用 SEH。 OP 的代码中不能使用 C++ 异常处理。
  • 令人惊讶的是,外部__try 的过滤器在内部__try__finally 之前执行。我同意@IInspectable 的观点,即关于应该如何最好使用螺丝刀来钉钉子的评论充其量只是误导。
  • @IInspectable 我删除了那句话,因为它离题了。
  • @Cheersandhth.-Alf:32 位和 64 位 SEH 之间唯一(显着)的区别是后者使用了基于表的异常处理。对于 32 位代码,编译器为每个 __try/__except 语句发出代码以设置基于堆栈的异常帧。对于 64 位 SEH,编译器在给定当前指令指针的情况下生成用于查找异常过滤器的表。这意味着 64 位代码在非抛出情况下表现出真正的零开销(忽略可执行映像大小的增加)。对于 SEH 和 C++ 异常处理都是如此。
【解决方案2】:

在微软网站上写了以下语句:

使用 longjmp 运行时函数退出 try-finally 语句被视为异常终止。跳入 __try 语句是非法的,但跳出一个是合法的。必须运行在出发点(__try 块的正常终止)和目的地(处理异常的 __except 块)之间处于活动状态的所有 __finally 语句。这称为局部放松。

它明确提到第一个 try 块被执行然后 _except 并且最后在退出 try 块之前它执行 finally 块。

参考。 https://msdn.microsoft.com/en-us/library/9xtt5hxz.aspx

【讨论】:

    猜你喜欢
    • 2023-04-09
    • 2012-08-17
    • 2014-12-13
    • 2011-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-30
    相关资源
    最近更新 更多