【问题标题】:SEH error reportingSEH 错误报告
【发布时间】:2011-04-06 16:01:32
【问题描述】:

我有一个 Visual Studio 2008 C++ 程序,该程序包含在 __try/__except 块中以捕获任何 SEH 异常。异常过滤器会创建错误日志并为用户提供有关如何提交缺陷报告的详细说明。

过滤器中的代码是否需要包装在另一个 __try/__except 块中?如果不是,如果它例外会发生什么?如果有,应该如何处理?

static int MyFilter( struct _EXCEPTION_POINTERS* ep )
{
    /*
    Code to log the exception information, and instruct the user 
    on how to submit a defect report. Should this be in another
    __try/__except block?
    */
    return EXCEPTION_EXECUTE_HANDLER;
}

int WINAPI _tWinMain( HINSTANCE hInstance, 
                      HINSTANCE /*hPrevInstance*/, 
                      LPTSTR lpstrCmdLine, 
                      int nCmdShow )
{
    int result = 0;

    __try
    {
        result = Execute( hInstance, lpstrCmdLine, nCmdShow );
    }
    __except( MyFilter( GetExceptionInformation() ) )
    {
        // empty
    }

    return 0;
}

谢谢, 保罗H


编辑: 如果MyFilter 引发异常,那么我将进入无限异常循环。所以,看起来它确实需要__try/__except 处理。我正在考虑这样做:

static int MyFilter( struct _EXCEPTION_POINTERS* ep )
{
    __try 
    {
        /*
        Code to log the exception information, and instruct the user 
        on how to submit a defect report. 
        */

       // cause an exception
       int x = 0, y = 1 / x;
    }
    __except( EXCEPTION_EXECUTE_HANDLER ) { /*empty*/ }
    return EXCEPTION_EXECUTE_HANDLER;
}

在这种情况下,程序应该有一个异常终止,并且应该将异常传递给操作系统来处理。对吗?

【问题讨论】:

    标签: c++ exception exception-handling seh structured-exception


    【解决方案1】:

    如果您在过滤器中引发异常,您将再次使用过滤器方法。您的异常将由同一个 __except 块处理。
    但是在您的过滤方法中使用另一个 __try __except 块没有问题。
    不幸的是,我不能给你任何参考。我自己试过了,你也可以。只需强制除以零。
    通常我不使用 SEH,但有几次我在过滤方法中引发异常时没有遇到任何问题。但是我在找这个的时候在msdn里没有找到任何东西。

    【讨论】:

    • 如果MyFilter 引发异常,那么我将进入无限异常循环。
    • 当然,如果它是相同的例外。正如我所说,您最终将进入相同的 __except 块,该块将再次调用您的过滤器函数。如果过滤器在第一个中抛出,它会在第二个中抛出,依此类推。
    • 我好像记得,如果在异常回调中发生未处理的SEH异常并且没有被捕获,那就被视为双重错误,进程被内核杀死。
    【解决方案2】:

    在执行此操作时,您需要注意很多事情。当您的 SEH 处理程序运行时,您的进程处于完全未知的状态,您尝试执行的一些指示用户的操作可能会失败。例如,如果异常是堆栈溢出,那么您在这里几乎无能为力。如果您在这里使用 UI 框架(例如 MFC),它可能会损坏或处于不一致的状态,因为您的应用程序可能在某些重要操作的中途崩溃。如果您的应用程序是多线程的,您需要知道当您进入此过滤器时其他线程仍将运行,并且可能需要小心处理。

    如果您确实需要这样做,另一种方法是使用看门狗进程来执行此操作。

    【讨论】:

    • 让我们假设异常过滤器中的代码完全是过滤器的本地代码(静态),并且在 ::MessageBox 之后不再使用 UI。 Windows(和 Windows Mobile)都有一个看门狗进程,但我想让我的应用有机会在 Watson 博士处理它之前记录错误。
    • 当然,这可能在大多数情况下都有效,但并不总是有效。例如,MessageBox 创建一个对话框并在您的线程堆栈上运行一个模式消息循环。如果您的堆栈被炸毁,那将无法正常工作。另一个风险是,使用模式对话框(例如屏幕上的消息框)时,在线程上创建的窗口的消息仍在被泵送,因此您的 wndprocs 仍可能被调用,这意味着即使您执行所有操作,您的正常应用程序代码仍然可以运行在您的异常处理程序中是“静态的”。修复这些东西并非不可能,但很难。
    • 既然你提到了 Windows Mobile(你之前没有提到 :))我对看门狗进程的建议可能不是那么好,因为 CE 5 有 32 个进程限制。一项服务或驱动程序这样做可能会更有效,因为如果进程限制有问题,服务和设备总是在运行。
    猜你喜欢
    • 2013-01-21
    • 1970-01-01
    • 1970-01-01
    • 2011-08-08
    • 2011-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多