簡體   English   中英

C ++ Visual Studio運行時錯誤

[英]C++ Visual Studio Runtime Error

任何人都可以向我解釋這意味着什么?

“運行時檢查失敗#0 - ESP的值未在函數調用中正確保存。這通常是調用使用一個調用約定聲明的函數,其中函數指針使用不同的調用約定聲明。”

在調用函數時,編譯器必須在堆棧上推送一些參數,或者將它們放在某些寄存器中。 函數體將更改某些內存位置(或寄存器)以包含返回值。 然后它將返回到堆棧上“某處”存儲的位置的代碼塊。

調用約定指定具體細節:例如,首先按下返回地址,然后從左到右推送堆棧上的參數(輸入或輸出),然后執行函數,再次關閉參數,然后彈出返回地址並跳轉到那個位置。

如果調用者以不同於函數期望的方式執行此操作,則可能會出錯(返回位置不在預期的堆棧位置)。

ESP通常是包含當前堆棧幀地址的寄存器。 該寄存器與索引結合使用以獲取函數體中的參數。 返回時,堆棧頂部通常重置為ESP,處理器跳轉到例如ESP + 1的位置。

可能導致這種情況發生的事情:

  • 有人寫了堆棧的值並更改了返回位置(例如緩沖區溢出)
  • 調用者具有與被調用者不同的調用約定

可能性#1是你的對象得到了別名錯誤。 這意味着編譯器錯誤地將對象錯誤地轉換為對象,最常見的是作為優化。

可能性#2您使用對無效對象的引用。

可能性#3完全不相關的東西打破了你的堆棧,可能是緩沖區溢出。

沒有代碼樣本除了這些可能性之外很難預測,但它們覆蓋了可能發生的90%。

這意味着在調用函數后,處理器ESP寄存器中的值未正確恢復。

正如已經說過的那樣,函數參數被推送到堆棧,並在函數結束后通過調整esp寄存器來轉儲。 在某些調用約定中,在調用代碼返回函數調用之后調整esp寄存器。 在其他約定中,它在被返回之前被調用的函數調整。

當在調用代碼和被調用的代碼之間產生關於誰調整esp的分歧時,我看到了這個錯誤。 仔細查看函數的聲明方式,特別是如果它位於單獨的庫或dll中。

在調用Windows API(如DialogBox)時,在轉換函數指針以關閉編譯器時通常會出現這種情況:

DialogBox(hInstance, MAKEINTRESOURCE(MY_DIALOG), hWnd, &dlgProc);

Windows有點奇怪,因為所有函數都是使用stdcall調用約定定義的,與cdecl相反,這是C中的默認值。因此,應該使用WINAPI(stdcall的定義)定義應傳遞給Windows API的所有函數:

INT_PTR WINAPI dlgProc(HWND, UINT, WPARAM, LPARAM);

如果你錯過了,而是將你的dlgProc定義為:

INT_PTR dlgProc(HWND, UINT, WPARAM, LPARAM);

您的代碼將無法編譯,您可能會非常想要關閉frikkin'編譯器:

DialogBox(hInstance, MAKEINTRESOURCE(MY_DIALOG), hWnd, (DLGPROC)&dlgProc); // be a DLGPROC already, dammit!!

不要那樣做。 該程序將崩潰。 編譯器是你的朋友。 C風格的演員不是。 編譯器試圖告訴你這將會發生。 這是對的。 聽這個。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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