如何在 Windows x64 C++ 应用程序中捕获堆栈溢出
Posted
技术标签:
【中文标题】如何在 Windows x64 C++ 应用程序中捕获堆栈溢出【英文标题】:How to trap stack overflow in a Windows x64 C++ application 【发布时间】:2015-03-30 14:47:19 【问题描述】:我正在尝试在 Windows 中将应用程序编译为 x64 平台架构。处理脚本语言解析的几个线程使用此代码recommended by Microsoft to trap stack overflows and avoid access violation exceptions:
__try
DoSomethingThatMightUseALotOfStackMemory();
__except(EXCEPTION_EXECUTE_HANDLER)
LPBYTE lpPage;
static SYSTEM_INFO si;
static MEMORY_BASIC_INFORMATION mi;
static DWORD dwOldProtect;
// Get page size of system
GetSystemInfo(&si);
// Find SP address
_asm mov lpPage, esp;
// Get allocation base of stack
VirtualQuery(lpPage, &mi, sizeof(mi));
// Go to page beyond current page
lpPage = (LPBYTE)(mi.BaseAddress)-si.dwPageSize;
// Free portion of stack just abandoned
if (!VirtualFree(mi.AllocationBase,
(LPBYTE)lpPage - (LPBYTE)mi.AllocationBase,
MEM_DECOMMIT))
exit(1);
// Reintroduce the guard page
if (!VirtualProtect(lpPage, si.dwPageSize,
PAGE_GUARD | PAGE_READWRITE,
&dwOldProtect))
exit(1);
Sleep(2000);
不幸的是,它使用一行内联汇编程序来获取堆栈指针。 Visual Studio 不支持 x64 模式的内联汇编,我也找不到用于获取堆栈指针的 compiler intrinsic。
是否可以以 x64 友好的方式执行此操作?
【问题讨论】:
msdn.microsoft.com/en-us/library/89f73td2.aspx @HansPassant :该链接实际上解决了问题。 _resetstkoflw 似乎是使用而不是上面的 hack 的调用。也许这应该作为正确的答案添加? 欢迎发布。 【参考方案1】:正如对该问题的评论中所指出的,上面的整个“hack”都可以替换为_resetstkoflw 函数。这在 x86 和 x64 模式下都可以正常工作。
那么上面的代码sn-p就变成了:
// Filter for the stack overflow exception. This function traps
// the stack overflow exception, but passes all other exceptions through.
int stack_overflow_exception_filter(int exception_code)
if (exception_code == EXCEPTION_STACK_OVERFLOW)
// Do not call _resetstkoflw here, because at this point
// the stack is not yet unwound. Instead, signal that the
// handler (the __except block) is to be executed.
return EXCEPTION_EXECUTE_HANDLER;
else
return EXCEPTION_CONTINUE_SEARCH;
void example()
int result = 0;
__try
DoSomethingThatMightUseALotOfStackMemory();
__except(stack_overflow_exception_filter(GetExceptionCode()))
// Here, it is safe to reset the stack.
result = _resetstkoflw();
// Terminate if _resetstkoflw failed (returned 0)
if (!result)
return 3;
return 0;
【讨论】:
以上是关于如何在 Windows x64 C++ 应用程序中捕获堆栈溢出的主要内容,如果未能解决你的问题,请参考以下文章
如何在不使用 C++ 中的 RegDeleteKeyEx 的情况下在 64 位树中删除 Windows x64 中的注册表项?
如何在 Windows 10 上使用 Visual Studio 2015 x64 配置和构建 Tesseract OCR C++
如何在 Win x64 上使用 WinAPI 正确安装虚拟打印机?
即使在安装 Visual C++ 2008 Express 和 Windows SDK 后也无法为 x64 编译
我需要安装啥来获得在 Windows Server 2012 R2 Standard 上运行的 C++ hello world .exe 的 x64 调试版本?