C++ Visual Studio 运行时错误

Posted

技术标签:

【中文标题】C++ Visual Studio 运行时错误【英文标题】:C++ Visual Studio Runtime Error 【发布时间】:2008-11-19 11:44:10 【问题描述】:

谁能给我解释一下这是什么意思?

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

【问题讨论】:

【参考方案1】:

当调用函数时,编译器必须将一些参数压入堆栈,或者将它们放入一些寄存器中。函数体将更改一些内存位置(或寄存器)以包含返回值。然后它将返回到存储在堆栈“某处”位置的代码块。

调用约定指定了具体细节:例如首先压入返回地址,然后从左到右将参数(输入或输出)压入堆栈,然后执行函数,再次弹出参数,然后弹出返回地址并跳转到该位置。

如果调用者执行此操作的方式与函数预期的不同,则可能会出错(返回位置不在预期的堆栈位置)。

ESP 通常是包含当前堆栈帧地址的寄存器。该寄存器与索引结合使用以获取函数体中的参数。返回时,堆栈顶部通常重置为 ESP,并且处理器跳转到例如ESP+1。

可能导致这种情况发生的事情:

有人改写了堆栈的值并更改了返回位置(例如缓冲区溢出) 调用者与被调用者的调用约定不同

【讨论】:

最后一个原因并不完全正确,应该是:'被调用者的调用约定与调用者假设的不同'。【参考方案2】:

可能性 #1 是您的对象别名错误。这意味着编译器错误地错误地转换了一个对象,最常见的是作为一种优化。

可能性 #2 您使用了对无效对象的引用。

可能性 #3 一些完全不相关的东西破坏了你的堆栈,可能是缓冲区溢出。

如果没有代码示例,除了这些可能性之外,很难预测,但它们涵盖了可能发生的 90%。

【讨论】:

【参考方案3】:

这意味着调用函数后处理器ESP寄存器中的值没有正确恢复。

如前所述,函数参数被压入堆栈,并在函数结束后通过调整 esp 寄存器转储。在某些调用约定中,esp 寄存器在函数调用返回后由调用代码进行调整。在其他约定中,它由被调用的函数调整,就在它返回之前。

当调用代码和被调用代码之间出现关于谁调整 esp 的分歧时,我看到了这个错误。仔细查看函数的声明方式,特别是如果它位于单独的库或 dll 中。

【讨论】:

【参考方案4】:

这通常是在调用 Windows API(例如 DialogBox)时强制转换函数指针以关闭编译器的情况:

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

Windows 有点奇怪,因为所有函数都是用 stdcall 调用约定定义的,这与 C 中的默认值 cdecl 不同。因此,所有应该传递给 Windows API 的函数都应该用 WINAPI 定义(为标准调用):

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 风格的强制转换运算符不是。编译器试图告诉你这将会发生。这是正确的。听听。

【讨论】:

以上是关于C++ Visual Studio 运行时错误的主要内容,如果未能解决你的问题,请参考以下文章

电脑问题 Microsoft visual c++ Runtime Library

在 Visual Studio 2019 中运行 python matplotlibcpp

可以从命令行运行 C++ 代码,但不能从 Visual Studio 中的调试模式运行

Visual Studio 2010在编译c++时为啥有错误也没有下划波浪线?

我电脑的visual studio code 运行不了c++?

Visual Studio 2010 的 Visual C++ 2012 运行时库先决条件