任何人都可以向我解释这意味着什么吗?
“运行时检查失败#0 - ESP的值未在函数调用中正确保存。这通常是调用使用一个调用约定声明的函数,其中函数指针使用不同的调用约定声明。 “
答案 0 :(得分:7)
调用函数时,编译器必须在堆栈上推送一些参数,或者将它们放在某些寄存器中。函数体将更改某些内存位置(或寄存器)以包含返回值。然后它将返回到堆栈中“某处”存储的位置的代码块。
调用约定指定具体细节:例如首先按下返回地址,然后从左到右推送堆栈上的参数(输入或输出),然后执行该函数,再次关闭参数,然后弹出返回地址并跳转到该位置。
如果调用者的行为与函数期望的不同,则可能出错(返回位置不在预期的堆栈位置)。
ESP通常是包含当前堆栈帧地址的寄存器。该寄存器与索引结合使用以获取函数体中的参数。当返回时,堆栈顶部通常被重置为ESP,并且处理器跳转到例如ESP处的位置。 ESP + 1。
可能导致这种情况发生的事情:
答案 1 :(得分:3)
可能性#1是你的对象得到了别名错误。这意味着编译器错误地错误地投放了一个对象,最常见的是作为优化。
可能性#2您使用对无效对象的引用。
可能性#3完全不相关的东西打破了你的堆栈,可能是缓冲区溢出。
没有代码示例除了这些可能性之外很难预测,但它们覆盖了可能发生的90%。
答案 2 :(得分:1)
这意味着在调用函数后,处理器ESP寄存器中的值未正确恢复。
正如已经说过的那样,函数参数被推送到堆栈,并在函数结束后通过调整esp寄存器来转储。在某些调用约定中,在调用代码返回函数调用之后调整esp寄存器。在其他约定中,它在被返回之前被调用的函数调整。
当调用代码和被调用代码之间出现关于谁调整esp的不一致时,我看到了这个错误。仔细查看函数的声明方式,特别是如果它位于单独的库或dll中。
答案 3 :(得分:0)
在调用Windows API(例如DialogBox)时,在编译函数指针以关闭编译器时通常就是这种情况:
DialogBox(hInstance, MAKEINTRESOURCE(MY_DIALOG), hWnd, &dlgProc);
Windows有点奇怪,因为所有函数都是用stdcall调用约定定义的,与cdecl相反,这是C中的默认值。因此,所有应该传递给Windows API的函数都应该用WINAPI定义(定义为STDCALL):
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风格的演员不是。编译器试图告诉你这将会发生。这是对的。听听它。