簡體   English   中英

如何在 x64 上創建“堆棧 oveflow”異常

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM