代码之家  ›  专栏  ›  技术社区  ›  unknown

StackOverflowException期间的矢量异常处理

  •  2
  • unknown  · 技术社区  · 16 年前

    如果我已经注册了自己的向量异常处理程序(veh),并且在我的进程中发生了stackoverflow异常,那么当我到达veh时,我将能够在堆栈上分配更多的内存吗?分配会导致我重写一些其他内存吗?会发生什么?
    我知道在.NET中,这就是为什么在创建线程的过程中提交了整个堆栈,但是假设我是用本机编写的,这样的场景会发生…在车内我能做什么?内存分配呢?

    3 回复  |  直到 11 年前
        1
  •  2
  •   GManNickG    16 年前

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

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

    // 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
    

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

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

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

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

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

        2
  •  1
  •   greenpiece    11 年前

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

    MSDN 明确地说:

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

        3
  •  0
  •   R Samuel Klatchko    16 年前

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

    如果您愿意预先分配地址空间(即只保留一系列地址而不实际分配内存),则可以使用 VirtualAlloc .首先,使用mem_reserve标志调用它来留出地址空间。稍后,在异常处理程序中,您可以使用mem-commit再次调用它,以将物理内存分配到预先保留的地址空间。