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