繁体   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