Weird MSC 8.0 error: “The value of ESP was not pro

2019-01-09 00:21发布

We recently attempted to break apart some of our Visual Studio projects into libraries, and everything seemed to compile and build fine in a test project with one of the library projects as a dependency. However, attempting to run the application gave us the following nasty run-time error message:

Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function pointer declared with a different calling convention.

We have never even specified calling conventions (__cdecl etc.) for our functions, leaving all the compiler switches on the default. I checked and the project settings are consistent for calling convention across the library and test projects.

Update: One of our devs changed the "Basic Runtime Checks" project setting from "Both (/RTC1, equiv. to /RTCsu)" to "Default" and the run-time vanished, leaving the program running apparently correctly. I do not trust this at all. Was this a proper solution, or a dangerous hack?

19条回答
疯言疯语
2楼-- · 2019-01-09 00:47

If you're using any callback functions with the Windows API, they must be declared using CALLBACK and/or WINAPI. That will apply appropriate decorations to make the compiler generate code that cleans the stack correctly. For example, on Microsoft's compiler it adds __stdcall.

Windows has always used the __stdcall convention as it leads to (slightly) smaller code, with the cleanup happening in the called function rather than at every call site. It's not compatible with varargs functions, though (because only the caller knows how many arguments they pushed).

查看更多
唯我独甜
3楼-- · 2019-01-09 00:48

do you have any typedef'd function prototypes (eg int (*fn)(int a, int b) )

if you dom you might be have gotten the prototype wrong.

ESP is an error on the calling of a function (can you tell which one in the debugger?) that has a mismatch in the parameters - ie the stack has restored back to the state it started in when you called the function.

You can also get this if you're loading C++ functions that need to be declared extern C - C uses cdecl, C++ uses stdcall calling convention by default (IIRC). Put some extern C wrappers around the imported function prototypes and you may fix it.

If you can run it in the debugger, you'll see the function immediatey. If not, you can set DrWtsn32 to create a minidump that you can load into windbg to see the callstack at the time of the error (you'll need symbols or a mapfile to see the function names though).

查看更多
The star\"
4楼-- · 2019-01-09 00:49

ESP is the stack pointer. So according to the compiler, your stack pointer is getting messed up. It is hard to say how (or if) this could be happening without seeing some code.

What is the smallest code segment you can get to reproduce this?

查看更多
三岁会撩人
5楼-- · 2019-01-09 00:49

Not the best answer but I just recompiled my code from scratch (rebuild in VS) and then the problem went away.

查看更多
啃猪蹄的小仙女
6楼-- · 2019-01-09 00:52

You would get this error if the function is invoked with a calling convention other than the one it is compiled to.

Visual Studio uses a default calling convention setting thats decalred in the project's options. Check if this value is the same in the orignal project settings and in the new libraries. An over ambitious dev could have set this to _stdcall/pascal in the original since it reduces the code size compared to the default cdecl. So the base process would be using this setting and the new libraries get the default cdecl which causes the problem

Since you have said that you do not use any special calling conventions this seems to be a good probability.

Also do a diff on the headers to see if the declarations / files that the process sees are the same ones that the libraries are compiled with .

ps : Making the warning go away is BAAAD. the underlying error still persists.

查看更多
何必那么认真
7楼-- · 2019-01-09 00:55

Silencing the check is not the right solution. You have to figure out what is messed up with your calling conventions.

There are quite a few ways to change the calling convetion of a function without explicitly specifying it. extern "C" will do it, STDMETHODIMP/IFACEMETHODIMP will also do it, other macros might do it as well.

I believe if run your program under WinDBG (http://www.microsoft.com/whdc/devtools/debugging/default.mspx), the runtime should break at the point where you hit that problem. You can look at the call stack and figure out which function has the problem and then look at its definition and the declaration that the caller uses.

查看更多
登录 后发表回答