如何构建一个捕获所有异常的C++ Dll Package 器?

hrirmatl  于 2023-01-28  发布在  其他
关注(0)|答案(8)|浏览(161)

正如标题所说,我们正在寻找一种方法来捕获一段C代码中的所有异常,并将其 Package 在一个dll中。这样我们就可以保护使用该dll的应用程序不受该dll中发生的任何错误的影响。
然而,这似乎不可能在Windows下使用C

示例:

void function()
{  
    try  
    {    
        std::list<int>::iterator fd_it;
        fd_it++;  
    } catch(...) {}
}

发生的异常不是由标准C++ try/catch块捕获的,也不是由_set_se_translator()设置的任何SEH转换器函数捕获的。相反,DLL崩溃,使用DLL的程序被中止。我们用Visual C++2005编译,带有选项/SHa。有人知道在C ++/Win32中是否有可能捕获这类问题并制作一个坚如磐石的DLL Package 器吗?

owfi6suc

owfi6suc1#

制作一个坚如磐石的DLL Package 器的唯一方法是将有缺陷的DLL加载到另一个进程中,这样,如果它崩溃了,它不会使您的主进程也随之崩溃。
捕获所有C++异常似乎是合理的,但捕获所有结构化异常则是另一回事。SEH似乎能帮你完成大部分任务,因为它允许你捕获访问违规、被零除异常等。
但是,如果有错误的DLL碰巧触及了另一个线程堆栈中未提交的页,该怎么办?内存访问将出现页错误,异常处理程序将被调用,现在该页不再是保护页。当该线程需要增加堆栈时,它将遇到访问冲突,进程将崩溃。(Theseposts将更详细地描述这种情况。)
另一个可能的问题是:有错误的DLL在持有同步对象时崩溃,但您使用SEH捕获异常。如果您的进程尝试获取相同的同步对象,则它会死锁而不是崩溃。共享同步对象可能是C运行时或OS:如果有缺陷的DLL 1加载了有缺陷的DLL 2,当有缺陷的DLL 1持有加载器锁时,DLL 2在它的DllMain()中崩溃了,那该怎么办?下次加载DLL时,你的进程会死锁吗?
有关为什么这(以及类似IsBadReadPtr()的函数,它们有类似的问题)是SEH的误用的更多信息:

6bc51xsx

6bc51xsx2#

在Windows上,C有两种不同风格的异常:C和SEH异常。
SEH是一个窗口特有的异常(有点类似于UNIX中的信号)。它更像是一个系统级的异常。它们会在诸如无效指针访问、对齐问题等操作中被抛出。
如果你想捕获Windows上C应用程序可能抛出的每个异常,你需要同时捕获两个异常。幸运的是,有一种方法可以混合使用C和SEH异常。我最近写了一篇关于这方面的详细博客文章,它应该会帮助你解决这个问题。
http://blogs.msdn.com/jaredpar/archive/2008/01/11/mixing-seh-and-c-exceptions.aspx

qxgroojn

qxgroojn3#

在标准库容器上递增迭代器永远不会抛出C++异常。它可能会给你带来未定义的行为。

c8ib6hqw

c8ib6hqw4#

下面的代码取自Zeus IDE。它将捕获任何Windows生成的异常:

**步骤#1:**定义例外过滤器函数

DWORD ExceptionFilter(EXCEPTION_POINTERS *pointers, DWORD dwException)
  {
    //-- we handle all exceptions
    DWORD dwResult = EXCEPTION_EXECUTE_HANDLER;

    switch (dwException)
    {
      case EXCEPTION_ACCESS_VIOLATION:
      case EXCEPTION_DATATYPE_MISALIGNMENT:
      case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
      case EXCEPTION_FLT_DENORMAL_OPERAND:
      case EXCEPTION_FLT_DIVIDE_BY_ZERO:
      case EXCEPTION_FLT_INEXACT_RESULT:
      case EXCEPTION_FLT_INVALID_OPERATION:
      case EXCEPTION_FLT_OVERFLOW:
      case EXCEPTION_FLT_STACK_CHECK:
      case EXCEPTION_FLT_UNDERFLOW:
      case EXCEPTION_INT_DIVIDE_BY_ZERO:
      case EXCEPTION_INT_OVERFLOW:
      case EXCEPTION_PRIV_INSTRUCTION:
      case EXCEPTION_NONCONTINUABLE_EXCEPTION:
      case EXCEPTION_BREAKPOINT:
        dwResult = EXCEPTION_EXECUTE_HANDLER;
        break;
    }

    return dwResult;
  }

**第2步:**将代码 Package 在 __try__except 中,如下所示:

__try
  {
    // call your dll entry point here
  }
  __except(ExceptionFilter(GetExceptionInformation(), 
                           GetExceptionCode()))
  {
    //-- display the fatal error message
    MessageBox(0, "An unexpected error was caught here!", 
               "Unexpected Error", MB_OK);
  }
mbjcgjjk

mbjcgjjk5#

康拉德·鲁道夫:当然,这段代码包含一个“逻辑错误”,这是为了说明一个可能发生的问题。就像那个人说他希望能够屏蔽他的dll免受任何可能的错误。你不认为这是一个合理的问题吗?听说过供应商的产品。我们中的一些人生活在真实的世界中,生活在真正的问题中。只是不可能修复其他人的问题

k10s72fa

k10s72fa6#

  • 此 * 代码包含一个逻辑错误,如果有的话。由于逻辑错误构成了一个bug,不要接受异常-修复错误

当然,这是针对特定代码的。其他人提供了更一般的建议。然而,我发现很多人实际上更喜欢捕捉异常而不是修复逻辑错误,这是完全不可接受的。

zzzyeukh

zzzyeukh7#

你看过Windows API函数SetUnhandledExceptionFilter吗?
我通常在DllMain函数中调用它,并在DLL崩溃时生成一个小型转储。(a)我不知道它是否能捕获应用程序异常以及DLL异常;(B)我不知道你是否能让处理程序以这样一种方式返回,使程序能够继续执行。

vptzau2j

vptzau2j8#

在捕获异常(特别是SEH异常)之后,您打算做什么?
实际上,您不能对进程的状态做任何假设,实际上,您拥有的唯一选项是(可选地)转储核心并退出。
从长远来看,任何尝试和行动都绝对会给你带来问题。

相关问题