我想做一个进程外异常处理程序,我创建了一个看门狗进程,当子进程引发异常时,它会执行专门的异常处理。我通过事件成功调用了监视程序进程。我面临的问题是在尝试将异常信息指针传递给另一个进程时。
我降落在这里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结构但不起作用。
答案 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会处理它。