C ++ Visual Studio运行时错误

时间:2008-11-19 11:44:10

标签: c++ visual-studio debugging

任何人都可以向我解释这意味着什么吗?

“运行时检查失败#0 - ESP的值未在函数调用中正确保存。这通常是调用使用一个调用约定声明的函数,其中函数指针使用不同的调用约定声明。 “

4 个答案:

答案 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风格的演员不是。编译器试图告诉你这将会发生。这是对的。听听它。