【问题标题】:Is it possible for a library consumer to override C++ exceptions handling?库使用者是否可以覆盖 C++ 异常处理?
【发布时间】:2009-05-27 07:03:53
【问题描述】:

我有一个 C++ DLL,代码如下:

LogMessage( "Hello world" );
try {
    throw new int;
} catch( int* e ) {
    LogMessage( "Caught exception" );
    delete e;
}
LogMessage( "Done" );

此 DLL 由某个第三方应用程序加载并调用上述代码。问题是只有第一个 LogMessage 被调用 - 即使有一个异常处理程序,控制流也会转移到未知数。

我看到了这一点,无法确定这是要调查的一些晦涩的错误还是只是消费者应用程序的邪恶力量。

消费者应用程序真的可以覆盖 DLL 中的 C++ 异常处理吗?

编辑:在考虑了答案中列出的所有要检查的事项后,问题得到了解决。在实际代码中,它不仅仅是throw,还有一个用于抛出异常的特殊函数,它在调试版本中调用了MessageBoxW() Win32 调用。并且消费者应用程序在显示消息框(它是一个 NT 服务)时遇到了麻烦,并且有效地挂断了。所以无论如何处理 C++ 异常都不是问题。

【问题讨论】:

    标签: c++ windows exception service messagebox


    【解决方案1】:

    代码对我来说看起来不错,但我很想在其中添加一些 catch 子句,看看它是否会碰到其他的一个。也就是说,我会输入:

    catch (const std::exception &ex) { ...记录异常... } 抓住 (...) { ...记录异常.. }

    我希望它会命中指针捕获(即使这真的不是一个好主意,请参阅 Igor Oks 提供的链接)或 std::exception 以防它无法分配内存。也就是说,它应该命中三个 catch 子句之一,因此异常无法逃脱 DLL。

    我还将抛出的对象更改为值类型(即使它是 int)并相应地更新 catch 子句以查看您是否以这种方式改变了行为。

    【讨论】:

    • 我接受这个答案,因为它提供了在调试此类问题时要检查的最广泛的事项列表。
    【解决方案2】:

    代码没问题。我用这个函数执行了它:

    void LogMessage( char* s )
    {
      cout << s << endl;
    }
    

    并得到正确的输出:

    世界你好

    捕获异常

    完成

    你的 LogMessage 函数可能有问题吗?

    我建议调查(通过调试器或添加调试打印),您的流程是否到达 try 块,以及它是否到达 catch 块。

    不是问题,仍然不清楚,通过抛出指针而不是值来实现什么。我建议不要使用 catch-by-pointer,请参阅 C++-FAQ-lite 中的推理 here

    【讨论】:

    • 极不可能。它第一次可以正常工作,看起来没有什么可以阻止它以后正常工作。
    【解决方案3】:

    首先,请检查LogMessage 调用是否刷新输出(使用&lt;&lt; endl)。

    虽然有点牵强,但新调用是否有可能抛出异常(内存不足)?我认为这是不出现新例外的一个原因(只是为了补充伊戈尔所说的)。

    【讨论】:

      【解决方案4】:

      代码看起来不错。但是你能在抛出结构化异常throw new int;之前检查是否有任何未处理的异常吗?

      LogMessage( "Hello world" );
      try {
      
           //some unhandled exception here 
      
          throw new int;
      } catch( int* e ) {
          LogMessage( "Caught exception" );
          delete e;
      }
      LogMessage( "Done" );
      

      如果是这种情况,那么您可以使用SetUnhandledExceptionFilter 函数进行检查。

      如果 DLL 已经提供了一个未处理的异常过滤器,并且如果它返回 EXCEPTION_EXECUTE_HANDLER,那么您的异常处理程序将不会被调用。

      您需要使用_set_se_translator 将win32 异常转换为c++ 结构化异常。

      【讨论】:

        【解决方案5】:

        赠品实际上在编辑中。 “MessageBoxW() ... NT 服务 ... 有效地挂断了。”。这是一个公平的描述。消息框位于未与登录用户关联的桌面上。因此,它仍然存在,等待永远不会发生的鼠标点击。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-03-06
          • 1970-01-01
          • 2018-11-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-09-06
          相关资源
          最近更新 更多