赶上出口(1);

时间:2009-03-08 10:04:47

标签: exception visual-c++ dll exit minidump

我有一个MFC SDI应用程序,它在启动时加载DLL。我只能查看源代码并使用DLL但不能更改&重新编译它。

现在的情况是,每当DLL引发错误时,它都会调用exit(),如下所示。

bool Func()
{
  // .. do something here

  if (error) { exit(999); }
}

在我的MFC应用程序中,我设置了SetUnhandledExceptionFilter来处理所有异常,并创建了一个MiniDump用于调试目的。

所以现在的问题是,每当DLL遇到任何错误时,它只会调用带有状态代码999的exit(),而我的ExceptionFilter将无法捕获它,因此没有为PostMortem调试创建MiniDump。

我很想知道是否:
1.我的全局异常处理程序是否还有其他方法可以捕获它? 2.我可以覆盖exit()函数,以便在调用时,我调用“throw(”error encounter!“)”并且我的全局异常处理程序可以捕获它。
3.我尝试在我的MFC应用程序中使用atexit(),每当DLL调用exit()时,我都会注册另一个函数来抛出错误。但似乎这种方法效果不佳。

我真正想做的是,每当DLL遇到错误时,我都希望生成一个MiniDump,这样我就可以进行PostMortem调试。在这种情况下还有其他什么可以发挥作用吗?

感谢。

4 个答案:

答案 0 :(得分:1)

检查DLL的符号导入表。

您可以将其重新映射到您在运行时选择的功能。

怎么做(假设退出那里):

大多数DLL通过跳转表使用符号导入。如果在调用者上设置断点,您将看到它调用了一个长跳转指令。跳转表是一个PAGE_EXECUTE_READWRITE页面,因此您可以使用自己的地址覆盖跳转表的那个插槽。

跳转表的位置会有所不同,但它始终是加载地址的常量偏移量,因此是任何函数指针到GetProcAddress找到的DLL的常量偏移量。

当然,所有这些都假设DLL永远不会改变。可能有一种方法可以在运行时找到所有这些东西,但我不知道你会怎么做。

哦,你不能从exit()返回。你必须长时间跳出来。

答案 1 :(得分:0)

这是我写的一个宏,用于在exit()函数中放置断点:

Imports System.IO

' Sets breakpoints on all exit functions.  useful for catching library code that 
' calls exit in the debugger.
Sub AddBreakpointsToExit()
    Dim bp As EnvDTE.Breakpoint
    Dim bps As EnvDTE.Breakpoints

    Dim envVar As String = "VS90COMNTOOLS"
    Dim comnTools As String = System.Environment.GetEnvironmentVariable(envVar)
    If (String.IsNullOrEmpty(comnTools)) Then
        Throw New System.Exception("Environment variable '" + envVar + "' doesn't exist.")
    End If
    Dim filePath As String = System.IO.Path.Combine(comnTools, "..\..\VC\crt\src\crt0dat.c")

    ' set exit function names and line #s:
    Dim exitFunctions(0 To 4) As String
    exitFunctions(0) = "exit"
    exitFunctions(1) = "_exit"
    exitFunctions(2) = "_cexit"
    exitFunctions(3) = "_c_exit"

    ' line numbers are based on the Visual Studio 2008 definition.
    ' TODO: check and add options if 2005 or 2010 are differen.t
    Dim exitLines(0 To 4) As Integer
    exitLines(0) = 412
    exitLines(1) = 420
    exitLines(2) = 427
    exitLines(3) = 434

    ' set breakpoints:
    For i = 0 To 3 Step 1
        bps = DTE.Debugger.Breakpoints.Add(File:=filePath, Line:=exitLines(i))
    Next i

End Sub

答案 2 :(得分:0)

我还没有找到解决方案,但是这里有一个可能的原因:atexit处理程序没有帮助:dll可能静态链接到CRT。这意味着exit()的代码直接构建在dll中,这将为其提供自己的私有退出处理程序列表,因此从主机进程中注册的atexit处理程序永远不会被看到。如果你能够在dll中调用atexit()(安排相当棘手),它可能会有效。

只是一个猜测 - 希望有所帮助。

答案 3 :(得分:0)

当进程正常退出时,每个DLL都会收到DLL_PROCESS_DETACH notification。如何编写自己的DLL,专门用于捕获此通知?