SEH StackOverflow异常 - 是否真的无法捕获?

Vip*_*per 1 c++ stack-overflow exception seh

SEH exceptions在StackOverflow和CodeProject.net上读过很多文章.

SEH exceptions在我的C++程序中实现处理后,我受到堆栈溢出异常的影响,我的软件没有捕获它.

经过下一部分研究后我明白,以编程方式检测这种异常是不可能的,因为我们没有可用的堆栈地址空间,因此程序内存已损坏.

我想问你有关处理堆栈溢出异常的经验.它看起来像是一个挑战,如果在非托管代码编程语言中不可能,我真的很感兴趣?

下面我将介绍我的示例程序(C++)的一部分,它可以重现stack overflow exception.它适用于任何SEH exception,但不是堆栈溢出:

LONG WINAPI SehHandler(PEXCEPTION_POINTERS pExceptionPtrs)
{ 
    cerr << "Handled SEH exception!\n";
    cerr << "ContextRecord: " << pExceptionPtrs->ContextRecord << endl;
    cerr << "ExceptionRecord: " << pExceptionPtrs->ExceptionRecord << endl;

    // Write minidump file
    CreateMiniDump(pExceptionPtrs);

    // Terminate process
    TerminateProcess(GetCurrentProcess(), 1); 

    return EXCEPTION_EXECUTE_HANDLER;
}

int fib(unsigned int n) {
    if(n == 0) return 0;
    if(n == 1) return 1;
    return fib(n-1)+fib(n-2);
}

int main(){
    SetUnhandledExceptionFilter(SehHandler); 
    cout << fib(1000000);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Han*_*ant 9

是的,你可以从一个SO崩溃中获得一个minidump,但从来没有你现在这样做的方式.您的SehHandler()函数在触发异常的线程上运行.它处于危险状态,你有大约7080字节的紧急堆栈空间可以做你需要做的事情.如果您使用该程序,则程序将因无法访问的访问冲突异常而失败.

你不能调用MiniDumpWriteDump()并希望能够存活它,该函数需要的堆栈比你可用的多.所以这是一个没有minidump的硬kaboom.

你需要另一个线程来进行这个调用.例如,这可能是您在初始化时创建的线程,并且使用WaitForMultipleObjects()调用进行阻塞.你的SehHandler()可以调用SetEvent()来唤醒它.将PEXCEPTION_POINTERS值写入全局变量后.并无限期地阻塞以允许线程创建minidump并中止进程.

Fwiw,到目前为止,该线程的最佳位置是另一个进程.这也允许你处理完全破坏过程状态的真正令人讨厌的那些.您在初始化时开始的"保护"过程.使用命名事件来发送信号,例如,使用内存映射文件传递PEXCEPTION_POINTERS.不要在SehHandler()中启动它,进程堆不再可靠,因此CreateProcess()不能再工作了,你必须尽早完成.

  • Hans,我明白你为什么没有回应 n0p,因为很明显紧急空间在哪里(在堆栈上)以及如何使用它(异常过滤器中的自动变量及其调用的函数)。但好奇的人想知道这个 7080 字节的数字来自哪里...... (2认同)