[英]How can i make "stack oveflow" exception on x64
我试图使“堆栈溢出”异常。
此代码在 x64 调试上引发异常。
void DumpSystem::makeStackOverflow()
{
static int callCount = 0;
++callCount;
makeStackOverflow();
}
但是,此代码不会在 x64 版本上引发异常 x64 版本 xxx.exe 是 LOOP,而不会导致“堆栈溢出”异常。
构建选项:“SEH(/EHa)”
我想使用“SetUnhandledExceptionFilter”创建一个“转储文件”。
这是我使用的代码
LONG saveDumpfile(EXCEPTION_POINTERS* ex);
unsigned __stdcall saveDumpFileForStackOverflow(void* arg)
{
EXCEPTION_POINTERS* ex = static_cast<EXCEPTION_POINTERS*>(arg);
return saveDumpfile(ex);
}
LONG exceptionHandling(EXCEPTION_POINTERS* ex)
{
if (ex &&
ex->ExceptionRecord &&
ex->ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW)
{
HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0,
saveDumpFileForStackOverflow, ex, NULL, NULL);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
return EXCEPTION_EXECUTE_HANDLER;
}
return saveDumpfile(ex);
}
void registrationDumpSystem()
{
::SetUnhandledExceptionFilter(exceptionHandling);
}
LONG saveDumpfile(EXCEPTION_POINTERS* ex)
{
if (ex == NULL)
return EXCEPTION_EXECUTE_HANDLER;
LONG result = EXCEPTION_EXECUTE_HANDLER;
//%APPDATA% : C:\Users\[user name]\AppData\Roaming
wstring filePath = getAppDataFolderPath();
SHCreateDirectoryEx(NULL, filePath.c_str(), NULL);
filePath.append(TEXT("\\Dump.dmp"));
HANDLE file = CreateFile(filePath.c_str(),
GENERIC_WRITE,
FILE_SHARE_WRITE,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
if (file == INVALID_HANDLE_VALUE)
{
DWORD lerr = GetLastError();
return lerr;
}
HANDLE processHandle = GetCurrentProcess();
DWORD processId = GetCurrentProcessId();
MINIDUMP_EXCEPTION_INFORMATION mei;
mei.ThreadId = GetCurrentThreadId();
mei.ExceptionPointers = ex;
mei.ClientPointers = false;
MiniDumpWriteDump(processHandle, processId, file,
MiniDumpNormal, &mei, NULL, NULL);
CloseHandle(file);
return result;
}
主程序
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
registrationDumpSystem();
//to do
return 0;
}
“x64 Debug exe”它是工作。 所以我可以制作“dump.dmp”文件。
但是,“x64 release exe”不起作用。 我无法制作“dump.dmp”文件
在此处输入图像描述我想知道为什么程序在 x64 版本上没有退出。
拜托,你能告诉我这个原因吗?
您犯了一个常见错误,那就是将您的 C++ 源代码视为人工指令到机器指令的一对一映射。 不是。 它是对程序的描述。 将这种描述转化为计算机可以执行的实际程序的过程非常复杂; 我们天真地认为现代编译器“优化”了代码,但这确实是一种倒退的方式来看待它。
事实上,编译器会尝试创建一个程序来做你想做的事,在给定这些约束的情况下产生最好的代码(或者稍微差一点的代码,如果你要求“低优化级别”,导致代码更多与您的源代码紧密匹配,从而允许更方便的调试)。 在这种情况下,您只是要求重复且无限地执行该函数的行为(实际上什么都没有)。
现在,如果将代码直接转换为递归的跳转序列等等,最终会导致堆栈溢出,因为所有函数上下文的堆栈空间都用完了。
但! “尾调用优化”存在。 在某些情况下,这是编译器可以做的事情,以产生更类似于循环而不是递归调用嵌套的东西。 在生成的代码中,不需要无限堆栈,因此也不例外。
如上所述,降低优化级别(这是调试版本往往涉及的内容),将导致“更糟糕”的代码与您编写的特定源代码更加匹配,并且您似乎在您的调试构建:即使不需要,也会产生实际的递归。 由于递归是无限的,您的程序会崩溃。
void DumpSystem::makeStackOverflow()
{
static int callCount = 0;
++callCount;
makeStackOverflow();
}
可以优化为类似的东西
void DumpSystem::makeStackOverflow()
{
static int callCount = 0;
while (true) ++callCount;
}
使用尾调用优化,如果这就是您的编译器正在做的事情,那么您将永远不会出现堆栈溢出。 您不会在调试模式下看到这种情况,因为调试模式通常不进行优化。
如果您想强制崩溃,有很多方法可以参考: 使 C++ 程序崩溃的最简单方法是什么?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.