You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为栈页设置PAGE_GUARD后无法触发自定义异常处理的问题

栈GUARD页异常无法捕获的原因与解决方案

你的推测完全正确:Windows会静默处理栈自动扩展相关的GUARD页违规异常,不会把这类异常抛给用户态的异常处理程序——不管是SetUnhandledExceptionFilter还是AddVectoredExceptionHandler都拿不到。

为什么你的代码没触发异常?

Windows的栈自动扩展机制本身就依赖GUARD页:线程栈创建时,内核会在栈的末端设置一个GUARD页。当程序访问这个GUARD页时,内核会自动完成以下操作,全程对用户态透明:

  • 移除该页的GUARD属性,转为普通读写页
  • 若栈还没达到设定的最大值,分配新的栈页并在新末端设置GUARD页
  • 让程序继续执行,不会把异常传递给用户态的异常处理链

你的代码里访问的stackTop - 0x1500属于未被程序使用过的栈区域,内核把这次访问当成了栈扩展请求,直接处理掉了异常,所以你的异常处理函数根本不会被调用。

能不能捕获这类异常?

用户态的限制

用户态下抓不到栈扩展触发的GUARD页异常——内核在用户态异常处理逻辑之前就把异常处理完了,异常根本不会进入用户态的异常处理流程。

能捕获的场景

如果你给已经被程序使用过的栈页手动加上GUARD属性,访问这类页时就会触发用户态异常。比如修改你的代码,先使用某个栈地址,再给对应页加GUARD:

#include <stdio.h>
#include <Windows.h>
#include <assert.h>

LONG WINAPI ExceptionHandler(_EXCEPTION_POINTERS* ExceptionInfo) {
    printf("捕获到异常代码: 0x%lx\n", ExceptionInfo->ExceptionRecord->ExceptionCode);
    
    // 移除GUARD属性,让程序可以继续执行
    MEMORY_BASIC_INFORMATION mbi;
    VirtualQuery((LPCVOID)ExceptionInfo->ExceptionRecord->ExceptionAddress, &mbi, sizeof(mbi));
    DWORD oldProtect;
    VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_READWRITE, &oldProtect);
    
    return EXCEPTION_CONTINUE_EXECUTION;
}

int main(void) {
    AddVectoredExceptionHandler(1, ExceptionHandler);

    // 先在栈上创建变量,确保该页被标记为已使用
    DWORD usedStackVar = 0;
    MEMORY_BASIC_INFORMATION mbi;
    VirtualQuery(&usedStackVar, &mbi, sizeof(mbi));

    // 给这个已使用的栈页添加GUARD属性
    DWORD savedProtect = 0;
    if(!VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_READWRITE | PAGE_GUARD, &savedProtect)){
        fprintf(stderr, "[Error]: 无法添加GUARD页: %ld\n", GetLastError());
        return 1;
    }

    // 访问已使用的栈页,会触发异常处理程序
    usedStackVar = 0xdeadbeef;
    printf("usedStackVar的值: 0x%x\n", usedStackVar);

    return 0;
}

要捕获栈扩展异常怎么办?

如果一定要捕获栈扩展触发的GUARD页异常,唯一的办法是写内核模式驱动,用KeRegisterExceptionCallback注册内核异常回调,在内核处理异常之前捕获STATUS_GUARD_PAGE_VIOLATION(0x80000001)。用户态没有任何途径能拿到这类异常。

内容的提问来源于stack exchange,提问作者Louis Kronberg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 19:20:27