【问题标题】:Vectored Exception Handling During StackOverflowExceptionStackOverflowException 期间的向量化异常处理
【发布时间】:2009-12-13 18:39:40
【问题描述】:

如果我注册了自己的向量异常处理程序 (VEH) 并且在我的进程中发生了 StackOverflow 异常,那么当我到达 VEH 时,我是否能够在堆栈上分配更多内存?分配会导致我覆盖其他一些内存吗?会发生什么?
我知道在 .Net 中,这就是为什么在线程创建期间提交整个堆栈的原因,但是假设我正在用本机编写并且发生这种情况......我将能够在 VEH 中做什么?内存分配呢..?

【问题讨论】:

    标签: c++ windows memory-management


    【解决方案1】:

    在堆栈溢出的情况下,您将需要处理一小部分堆栈。堆栈足够启动一个新线程,该线程将拥有一个全新的堆栈。从那里,您可以在终止之前做任何您需要做的事情。

    您无法从堆栈溢出中恢复,这将涉及展开堆栈,但您的整个程序将在此过程中被破坏。这是我为堆栈转储实用程序编写的一些代码:

    // stack overflows cannot be handled, try to get output then quit   
    set_current_thread(get_current_thread());
    boost::thread t(stack_fail_thread);
    
    t.join(); // will never exit
    

    所有这些都是获取线程的句柄,因此堆栈转储机制知道要转储哪个线程,启动一个新线程来进行转储/记录,并等待它完成(这不会发生,线程调用 @ 987654322@).

    为了完整起见,get_current_thread() 看起来像这样:

    const HANDLE process = GetCurrentProcess();
    HANDLE thisThread = 0;
    DuplicateHandle(process, GetCurrentThread(), process,
            &thisThread, 0, true, DUPLICATE_SAME_ACCESS);
    

    所有这些都是“简单”的函数,不需要很大的工作空间(请记住,编译器可能会内联这些 msot,删除函数调用)。相反,您不能抛出异常。这不仅需要更多的工作,而且析构函数可以做很多工作(比如释放内存),这往往也很复杂。

    最好的办法是启动一个新线程,尽可能多地保存有关应用程序的信息,然后终止。

    【讨论】:

      【解决方案2】:

      不,您不能在向量异常处理程序中分配内存。

      MSDN 明确表示:

      "处理程序不应调用获取同步对象或分配内存的函数,因为这会导致问题。通常,处理程序将简单地访问异常记录并返回。”

      【讨论】:

        【解决方案3】:

        堆栈需要是连续的,因此您不能只分配任何随机内存,而必须分配地址空间的下一部分。

        如果你愿意预先分配地址空间(即只保留一个地址范围而不实际分配内存),你可以使用VirtualAlloc。首先,您使用 MEM_RESERVE 标志调用它以留出地址空间。稍后,在您的异常处理程序中,您可以使用 MEM_COMMIT 再次调用它,以将物理内存分配给您预先保留的地址空间。

        【讨论】:

        • “堆栈溢出异常”背后的整个想法是我在堆栈上分配的内存比我原来保留的要多。因此,如果我超出了保留的大小,则会引发 stackoverflow 异常,并且我将到达 VEH .. 但在这种情况下,我能否在堆栈上分配更多内存? (我的意思是在 VEH 的体内)
        猜你喜欢
        • 1970-01-01
        • 2021-05-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多