使用FileMapping传递_EXCEPTION_POINTERS *时遇到问题

时间:2013-04-22 13:01:10

标签: c++ shared-memory crash-dumps file-mapping

我想做一个进程外异常处理程序,我创建了一个看门狗进程,当子进程引发异常时,它会执行专门的异常处理。我通过事件成功调用了监视程序进程。我面临的问题是在尝试将异常信息指针传递给另一个进程时。

我降落在这里Passing a pointer to process spawned with exec()并且知道在共享内存中传递指针有这个问题:

“如果使用共享内存,则无法传递指针。指针将包含虚拟地址,该地址不同于一个进程。您必须根据共享内存的开始交换偏移值区域。

如果您不使用共享内存,则无法交换任何类型的指针:其他进程将无法访问进程的内存。“

现在我怎么能克服这个?

流程1:

    struct mytest
    {
      _EXCEPTION_POINTERS * except ;
      DWORD ThreadId ;
      DWORD ProcessId ;
    }

    OpenFileMapping ( ) ;

    void * pBuf = MapViewOfFile ( ) ;

    mytest passdata ;

    CopyMemory ( pBuf , &passdata , sizeof ( passdata ) ) ;

    UnMapView ( ) ;

    CloseHandle ( ) ;

(例如)流程2:

    cout << passdata->except->ExceptionRecord->ExceptionCode << endl ;

会崩溃。我理解这是因为虚拟地址是特定于进程的。但是在这种情况下如何将异常信息传递给不同的进程并编写一个minidump?

P.S:我甚至尝试单独传递PEXCEPTION_RECORD结构但不起作用。

2 个答案:

答案 0 :(得分:3)

我会把这些作为一个答案,尽管它应该是对Hans's answer(以及那里的评论)的评论,但似乎有必要作出一些解释:

问题中发布的代码正确地将struct mytest结构的值传递到共享内存中。

第二个代码段:

  

(例如)流程2:

cout << passdata->except->ExceptionRecord->ExceptionCode << endl ;

虽然显示了一个误解:虽然你可以读取指针passdata.except的值,但在进程2中这只是一个任意的32/64位值,它不是一个有效的指针。

可以将此传递给MiniDumpWriteDump,此函数将在目标进程(proc 1)的上下文中显示此指针值。但是你不能在过程#2中取消引用它。

Hans的例子给出了解决方案,如果你需要在进程#2中使用ExeptionCode的值,那么你需要取消引用proc#1中的指针并将值放入你写入共享内存的数据中。 / p>

答案 1 :(得分:1)

是的,你不能在另一个进程中取消引用指针,它只在崩溃的进程中有效。只传递给MiniDumpWriteDump(),MINIDUMP_EXCEPTION_INFORMATION.ExceptionPointers字段。从技术上讲,你可以使用ReadProcessMemory(),但是对于崩溃的进程这样做是不必要的风险。简单的解决方案是在结构中添加一个额外的字段,用于存储异常代码并由异常过滤器编写。

mytest passdata ;
passdata.except = ExceptionInfo;
// Note: added field
passdata.ExceptionCode = ExceptionInfo->ExceptionRecord->ExceptionCode;
passdata.ThreadId = GetCurrentThreadId();
// etc..

同时避免调用OpenFileMapping和MapViewOfFile等winapi函数,它风险太大。当程序因进程堆的堆损坏而崩溃时,它们往往会死锁。崩溃和死锁的常见原因,因为仍然保持堆锁。在程序初始化时这样做。您也不需要打扰清理,当您的监视程序进程在获取minidump后终止崩溃进程时,Windows会处理它。