Calling convention for dynamically created function in (Visual) C++ - c++

I use the following types to create a new function at runtime:
typedef int (*pfunc)(int);
union funcptr {
pfunc x;
byte* y;
};
This enables me to write instructions in y and afterwards call the function like this:
byte* p = (byte*)VirtualAllocEx(GetCurrentProcess(), 0, 1<<16, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
// Write some instructions to p
funcptr func;
func.y = p;
int ret = func.x(arg1); // Call the generated function
It is crucial to know how C++ prepare arguments (call convention) and therefore I have looked up the project properties (Visual C++) and I can see it uses __cdecl. It should put arguments on the stack according to: http://msdn.microsoft.com/en-us/library/aa271989(v=vs.60).aspx and http://en.wikipedia.org/wiki/X86_calling_conventions#cdecl but when I look at the assembly generated, the argument is moved to the EAX register.
I want to be absolutely certain how the arguments is prepared. So have I overlooked something about cdecl or is Visual C++ optimizing the call, and if so, how do I ensure it doesn't happen?
Best regards, Lasse Espeholt

The EAX register is used for the return value of the function. You state in the comments that you are compiling using /Gd and so the function will use __cdecl. All the same it would make sense in my view to mark the declaration of your function type pfunc with an explicit __cdecl so that there can be no scope for confusion and mis-match.
Of course, there's nothing to stop you using one of the other calling conventions supported by your compiler. The most important point is that whatever calling convention you settle on, you should explicitly specify the calling convention for the function pointer since the compiler is only responsible for one half of the interface.

At least on Linux, you probably want to use libffi (foreign function interface), and it has even been ported to other systems (including Windows).
And if you want to do machine code generation at runtime, consider using GNU lightning, DotGnu's libjit, LLVM. LuaJit's dynasm etc You could also generate C code into foo.c, get it compiled by forking a gcc -fPIC -shared foo.c -o foo.so command, and dlopen("./foo.so", RTLD_GLOBAL) (and Windows have equivalent ability)

Related

“The value of ESP was not properly saved across a function call.”

I have a DLL written in Delphi 7 that I need to use in Visual C++ 2008.
From documentation that came with DLL, I can see that function is declared as (Delphi 7):
function ReadInfo(pCOM, pBuf, pErr: Pointer):boolean;
where pCom is pointer to data structure:
TCOM = record
dwBaudRate: Longword;
nCom,
nErr,
nLang : Byte;
end;
pBuf is pointer to "array of byte" (as it is written in DLL's documentation).
pErr - not used.
So now in c++ (after successfully loading DLL with LoadLibrary), I call:
myFunc = (MY_FUNC_POINTER)GetProcAddress(dllHandle, "ReadInfo");
which also doesn't return any errors.
MY_FUNC_POINTER is defined as:
typedef bool (*MY_FUNC_POINTER)(TCOM*, BYTE*, void*);
where TCOM is:
struct TCOM
{
unsigned long dwBaudRate;
BYTE nComm;
BYTE nError;
BYTE nLanguage;
};
I defined:
TCOM MyCom;
BYTE *myRes;
myRes = new BYTE[1024*1024];
But after calling
myFunc(&MyCom, myRes, NULL)
I get “The value of ESP was not properly saved across a function call.” error.
There would appear to be a calling convention mismatch. On the face of it, the function declares no calling convention in the Delphi, so the default Borland register convention is used. Your C++ code does not declare a calling convention for the import so the default of cdecl is used. But it is plausible that the Delphi code and documentation are not aligned and the Delphi code actually uses a different calling convention. Check the Delphi code, or contact the vendor. No matter what, the error message that you report does indicate a binary mis-match across the boundary between your module and the other module.
If the function really does use the Borland register calling convention (but see below for more), then you cannot readily call the function from languages other than Delphi. In that case you'd need a bridge to adapt that to a standard calling convention such as stdcall. By that I mean a Delphi DLL that can call the original DLL and expose it's functionality a way suited to interop. A better solution would be to fix the root problem and build the DLL again using standard calling conventions.
In fact, I now suspect that all the other commentators are correct. I suspect that the Delphi documentation does not match the Delphi code. I suspect that the function really is stdcall. So you can, probably, solve your problem by changing the function pointer typedef to be as follows:
typedef bool (__stdcall *MY_FUNC_POINTER)(TCOM*, BYTE*, void*);
My reasoning for this is that in stdcall the callee is responsible for cleaning the stack. That's not the case for cdecl, and since all the parameters, and the return value, fit in registers, it's not the case for Delphi register calling convention, for this function. Since there is a stack pointer mis-match, it follows that the most likely explanation is that the Delphi function is stdcall.
All the same, it's not comfortable to be working out calling conventions this way. If you cannot get any help from the DLL vendor then I'd be inclined to dig a little deeper by looking at the DLL function's code under a disassembler.

MSVS 2010 C++ Compiler and Stack alignment issue?

My problem is MSVS 2010 C++ compiler is generating code in a way after returning from a function call resolved in runtime(GetProcAddress+GetModuleHandle) from another dll the compiler then tries to align stack this way:
CALL DWORD PTR DS:[2000367C] ; apiresolvedinruntime.dll
ADD ESP,12 ; <- this is the stack alignment
This is of course overwriting the return address and my program crashes, can someone explain me why compiler aligning the stack when it really shouldn't do it?
You didn't call the runtime loaded function using the correct calling convention. Calling convention specifies the default handling of what happens to the stack. Most likely, the DLL was compiled using the __stdcall calling convention (which is what e.g. the Windows DLLs use), which specifies that the called function is supposed to clean up the stack, but the calling code was declared with a function pointer using the __cdecl calling convention (which is the default). Under __cdecl, functions support variadic arguments, so the caller needs to do the cleanup of the stack, because the called function does not know how many arguments are passed.
You need to verify that the DLL and the calling code are compiled using the same calling conventions.

__cdecl results in larger executable than __stdcall?

I found this:
Because the stack is cleaned by the called function, the __stdcall
calling convention creates smaller executables than __cdecl, in which
the code for stack cleanup must be generated for each function call.
Suppose I got 2 functions:
void __cdecl func1(int x)
{
//do some stuff using x
}
void __stdcall func2(int x, int y)
{
//do some stuff using x, y
}
and here in the main():
int main()
{
func1(5);
func2(5, 6);
}
IMO, it is main()'s responsibility to clean up the stack of the call to func1(5), and func2 will clean up the stack of the call to func2(5,6), right?
Four questions:
1.For the call to func1 in main(), it's main's responsibility to clean up the stack, so will compiler insert some code (code to clean up the stack) before and after the call to func? Like this:
int main()
{
before_call_to_cdecl_func(); //compiler generated code for stack-clean-up of cdecl-func-call
func1(5);
after_call_to_cdecl_func(); //compiler generated code for stack-clean-up of cdecl-func-call
func2(5, 6);
}
2.For the call to func2 in main(), it's func2's own job to clean up the stack, so I presume, no code will be inserted in main() before or after the call to func2, right?
3.Because func2 is __stdcall, so I presume, compiler will automatically insert code (to clean up the stack) like this:
void __stdcall func1(int x, int y)
{
before_call_to_stdcall_func(); //compiler generated code for stack-clean-up of stdcall-func-call
//do some stuff using x, y
after_call_to_cdecl_func(); //compiler generated code for stack-clean-up of stdcall-func-call
}
I presume right?
4.Finally, back to the quoted words, why __stdcall results in smaller executable than __cdecl? And there is no such a thing as __stdcall in linux, right? Does it means linux elf will be always larger than exe in win?
It'll only insert code after the call, which is to reset the stack pointer, so long as there where call arguments.*
__stdcall generates no cleanup code at the call site, however, it should be noted that compilers can accrue stack cleanup from multiple __cdecl calls into one cleanup, or it can delay the cleanup to prevent pipeline stalls.
Ignoring the inverted order in this example, no, it'll only insert code to cleanup the __cdecl function, setting up of function arguments is something different (different compilers generate/prefer different methods).
__stdcall was more a windows thing, see this. the size of the binary depends on the number of calls to the __cdecl funcs, more calls means more clean up code, where as __stdcall has only 1 singular instance of cleanup code. however, you shouldn't see that much size increase, as at most you have a few bytes per call.
*Its important to distinguish between cleanup and setting up call parameters.
Historically, the first C++ compilers used the equivalent of
__stdcall. From a quality of implementation point of view, I'd expect
the C compiler to use the __cdecl convensions, and the C++ compiler
the __stdcall (which were known as the Pascal convensions back then).
This is one thing that the early Zortech compiles got right.
Of course, vararg functions must still use __cdecl conventions. The
callee can't clean up the stack if it doesn't know how much to clean up.
(Note that the C standard was carefully designed to allow the
__stdcall conventions in C as well. I only know of one compiler which
took advantage of this, however; the amount of existing code at the time
which called vararg functions without a prototype in view was enormous,
and while the standard declared it broken, compiler implementors didn't
want to break their clients' code.)
In a lot of milieu, there seems to be a very strong tendency to insist
that the C and the C++ conventions be the same, that one can take the
address of an extern "C++" function, and pass it to a function written
in C which calls it. IIRC, for example, g++ doesn't treat
extern "C" void f();
and
void f();
as having two different types (although the standard requires it), and
allows passing the address of a static member function to
pthread_create, for example. The result is that such compilers use
the exact same conventions everywhere, and on Intel, they are the
equivalent of __cdecl.
Many compilers have extensions to support other convensions. (Why they
don't use the standard extern "xxx", I don't know.) The syntax for
these extensions is very varied, however. Microsoft puts the attribute
directly before the function name:
void __stdcall func( int, int );
, g++ puts it in a special attribute clause after the function
declaration:
void func( int, int ) __attribute__((stdcall));
The C++11 has added a standard way of specifying attributes:
void [[stdcall]] func( int, int );
It doesn't specify stdcall as an attribute, but it does specify that
additional attributes (other than those defined in the standard) may be
specified, and are implementation dependent. I expect that both g++ and
VC++ accept this syntax in their most recent versions, at least if C++11
is activated. The exact name of the attribute (__stdcall, stdcall,
etc.) may vary, however, so you probably want to wrap this in a macro.
Finally: in a modern compiler with optimization turned on, the
difference in the calling conventions is probably negligible.
Attributes like const (not to be confused with the C++ keyword
const), regparm or noreturn will probably have a larger impact,
both in terms of executable size and performance.
This calling convention crowd is history by the new 64-bit ABI.
http://en.wikipedia.org/wiki/X86_calling_conventions#x86-64_calling_conventions
There is also the ABI side of things for different architectures. (like ARM)
Not everything executes the same for all architectures. So do not bother thinking about this calling convention thing !
http://en.wikipedia.org/wiki/Calling_convention
EXE size improvement is insignificant (maybe nonexistent), do not bother...
__cdecl is much more flexible than __stdcall. Variable number of arguments flexibility, the insignificance of cleanup code (instruction), __cdecl function can be called with wrong number of arguments and this does not necessarily cause a serious problem ! But the same situation with __stdcall always goes wrong !
Others have answered the other parts of your question, so I'll just add my answer about the size:
4.Finally, back to the quoted words, why __stdcall results in smaller executable than __cdecl?
That appears to not be true. I tested it by compiling libudis with and without the stdcall calling convention. First without:
$ clang -target i386-pc-win32 -DHAVE_CONFIG_H -Os -I.. -I/usr/include -fPIC -c *.c && strip *.o
$ du -cb *.o
6524 decode.o
95932 itab.o
1434 syn-att.o
1706 syn-intel.o
2288 syn.o
1245 udis86.o
109129 totalt
And with. It is the -mrtd switch that enables stdcall:
$ clang -target i386-pc-win32 -DHAVE_CONFIG_H -Os -I.. -I/usr/include -fPIC -mrtd -c *.c && strip *.o
7084 decode.o
95932 itab.o
1502 syn-att.o
1778 syn-intel.o
2296 syn.o
1305 udis86.o
109897 totalt
As you can see, cdecl beats stdcall with a few hundred bytes. It could be my testing methodology that is flawed, or clang's stdcall code generator is weak. But I think that with modern compilers the extra flexibility afforded by caller cleanup means that they will always generate better code with cdecl rather than stdcall.

Why do thread functions need to be declared as '__cdecl'?

Sample code that shows how to create threads using MFC declares the thread function as both static and __cdecl. Why is the latter required? Boost threads don't bother with this convention, so is it just an anachronism?
For example (MFC):
static __cdecl UINT MyFunc(LPVOID pParam)
{
...
}
CWinThread* pThread = AfxBeginThread(MyFunc, ...);
Whereas Boost:
static void func()
{
...
}
boost::thread t;
t.create(&func);
(the code samples might not be 100% correct as I am nowhere near an IDE).
What is the point of __cdecl? How does it help when creating threads?
__cdecl tells the compiler to use the C calling convention (as opposed to the stdcall, fastcall or whatever other calling convention your compiler supports). I believe, VC++ uses stdcall by default.
The calling convention affects things such as how arguments are pushed onto the stack (or registers, in the case of fastcall) and who pops arguments off the stack (caller or callee).
In the case of Boost. I believe it uses template specialization to figure out the appropriate function type and calling convention.
Look at the prototype for AfxBeginThread():
CWinThread* AfxBeginThread(
AFX_THREADPROC pfnThreadProc,
LPVOID pParam,
int nPriority = THREAD_PRIORITY_NORMAL,
UINT nStackSize = 0,
DWORD dwCreateFlags = 0,
LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL
);
AFX_THREADPROC is a typedef for UINT(AFX_CDECL*)(LPVOID). When you pass a function to AfxBeginThread(), it must match that prototype, including the calling convention.
The MSDN pages on __cdecl and __stdcall (as well as __fastcall and __thiscall) explain the pros and cons of each calling convention.
The boost::thread constructor uses templates to allow you to pass a function pointer or callable function object, so it doesn't have the same restrictions as MFC.
Because your thread is going to be called by a runtime function that manages this for you, and that function expects it to be that way. Boost designed it a different way.
Put a breakpoint at the start of your thread function and look at the stack when it gets called, you'll see the runtime function that calls you.
C/C++ compilers by default use the C calling convention (pushing rightmost param first on the stack) for it allows working with functions with variable argument number as printf.
The Pascal calling convention (aka "fastcall") pushes leftmost param first. This is quicker though costs you the possibility of easy variable argument functions (I read somewhere they're still possible, though you need to use some tricks).
Due to the speed resulting from using the Pascal convention, both Win32 and MacOS APIs by default use that calling convention, except in certain cases.
If that function has only one param, in theory using either calling convention would be legal, though the compiler may enforce the same calling convention is used to avoid any problem.
The boost libraries were designed with an eye on portability, so they should be agnostic as to which caller convention a particular compiler is using.
The real answer has to do with how windows internally calls the thread proc routine, and it is expecting the function to abide by a specific calling convention, which in this case is a macro, WINAPI, which according to my system is defined as:
#define WINAPI __stdcall
This means that the called function is responsible for cleaning up the stack. The reason why boost::thread is able to support arbitrary functions is that it passes a pointer to the function object used in the call to thread::create function to CreateThread. The threadproc associated with the thread simply calls operator() on the function object.
The reason MFC requires __cdecl therefore has to do with the way it internally calls the function passed in to the call to AfxBeginThread. There is no good reason to do this unless they were planning on allowing vararg parameters...

Weird MSC 8.0 error: "The value of ESP was not properly saved across a function call..."

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?
This debug error means that the stack pointer register is not returned to its original value after the function call, i.e. that the number of pushes before the function call were not followed by the equal number of pops after the call.
There are 2 reasons for this that I know (both with dynamically loaded libraries). #1 is what VC++ is describing in the error message, but I don't think this is the most often cause of the error (see #2).
1) Mismatched calling conventions:
The caller and the callee do not have a proper agreement on who is going to do what. For example, if you're calling a DLL function that is _stdcall, but you for some reason have it declared as a _cdecl (default in VC++) in your call. This would happen a lot if you're using different languages in different modules etc.
You would have to inspect the declaration of the offending function, and make sure it is not declared twice, and differently.
2) Mismatched types:
The caller and the callee are not compiled with the same types. For example, a common header defines the types in the API and has recently changed, and one module was recompiled, but the other was not--i.e. some types may have a different size in the caller and in the callee.
In that case, the caller pushes the arguments of one size, but the callee (if you're using _stdcall where the callee cleans the stack) pops the different size. The ESP is not, thus, returned to the correct value.
(Of course, these arguments, and others below them, would seem garbled in the called function, but sometimes you can survive that without a visible crash.)
If you have access to all the code, simply recompile it.
I read this in other forum
I was having the same problem, but I just FIXED it. I was getting the same error from the following code:
HMODULE hPowerFunctions = LoadLibrary("Powrprof.dll");
typedef bool (*tSetSuspendStateSig)(BOOL, BOOL, BOOL);
tSetSuspendState SetSuspendState = (tSuspendStateSig)GetProcAddress(hPowerfunctions, "SetSuspendState");
result = SetSuspendState(false, false, false); <---- This line was where the error popped up.
After some investigation, I changed one of the lines to:
typedef bool (WINAPI*tSetSuspendStateSig)(BOOL, BOOL, BOOL);
which solved the problem. If you take a look in the header file where SetSuspendState is found (powrprof.h, part of the SDK), you will see the function prototype is defined as:
BOOLEAN WINAPI SetSuspendState(BOOLEAN, BOOLEAN, BOOLEAN);
So you guys are having a similar problem. When you are calling a given function from a .dll, its signature is probably off. (In my case it was the missing WINAPI keyword).
Hope that helps any future people! :-)
Cheers.
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.
I saw this error when the code tried to call a function on an object that was not of the expected type.
So, class hierarchy: Parent with children: Child1 and Child2
Child1* pMyChild = 0;
...
pMyChild = pSomeClass->GetTheObj();// This call actually returned a Child2 object
pMyChild->SomeFunction(); // "...value of ESP..." error occurs here
I was getting similar error for AutoIt APIs which i was calling from VC++ program.
typedef long (*AU3_RunFn)(LPCWSTR, LPCWSTR);
However, when I changed the declaration which includes WINAPI, as suggested earlier in the thread, problem vanished.
Code without any error looks like:
typedef long (WINAPI *AU3_RunFn)(LPCWSTR, LPCWSTR);
AU3_RunFn _AU3_RunFn;
HINSTANCE hInstLibrary = LoadLibrary("AutoItX3.dll");
if (hInstLibrary)
{
_AU3_RunFn = (AU3_RunFn)GetProcAddress(hInstLibrary, "AU3_WinActivate");
if (_AU3_RunFn)
_AU3_RunFn(L"Untitled - Notepad",L"");
FreeLibrary(hInstLibrary);
}
It's worth pointing out that this can also be a Visual Studio bug.
I got this issue on VS2017, Win10 x64. At first it made sense, since I was doing weird things casting this to a derived type and wrapping it in a lambda. However, I reverted the code to a previous commit and still got the error, even though it wasn't there before.
I tried restarting and then rebuilding the project, and then the error went away.
I was getting this error calling a function in a DLL which was compiled with a pre-2005 version of Visual C++ from a newer version of VC (2008).
The function had this signature:
LONG WINAPI myFunc( time_t, SYSTEMTIME*, BOOL* );
The problem was that time_t's size is 32 bits in pre-2005 version, but 64 bits since VS2005 (is defined as _time64_t). The call of the function expects a 32 bit variable but gets a 64 bit variable when called from VC >= 2005. As parameters of functions are passed via the stack when using WINAPI calling convention, this corrupts the stack and generates the above mentioned error message ("Run-Time Check Failure #0 ...").
To fix this, it is possible to
#define _USE_32BIT_TIME_T
before including the header file of the DLL or -- better -- change the signature of the function in the header file depending on the VS version (pre-2005 versions don't know _time32_t!):
#if _MSC_VER >= 1400
LONG WINAPI myFunc( _time32_t, SYSTEMTIME*, BOOL* );
#else
LONG WINAPI myFunc( time_t, SYSTEMTIME*, BOOL* );
#endif
Note that you need to use _time32_t instead of time_t in the calling program, of course.
I was having this exact same error after moving functions to a dll and dynamically loading the dll with LoadLibrary and GetProcAddress. I had declared extern "C" for the function in the dll because of the decoration. So that changed calling convention to __cdecl as well. I was declaring function pointers to be __stdcall in the loading code. Once I changed the function pointer from __stdcall to__cdecl in the loading code the runtime error went away.
Are you creating static libs or DLLs? If DLLs, how are the exports defined; how are the import libraries created?
Are the prototypes for the functions in the libs exactly the same as the function declarations where the functions are defined?
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).
Another case where esp can get messed up is with an inadvertent buffer overflow, usually through mistaken use of pointers to work past the boundary of an array. Say you have some C function that looks like
int a, b[2];
Writing to b[3] will probably change a, and anywhere past that is likely to hose the saved esp on the stack.
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.
This happened to me when accessing a COM object (Visual Studio 2010). I passed the GUID for another interface A for in my call to QueryInterface, but then I cast the retrieved pointer as interface B. This resulted in making a function call to one with an entirely signature, which accounts for the stack (and ESP) being messed up.
Passing the GUID for interface B fixed the problem.
In my MFC C++ app I am experiencing the same problem as reported in Weird MSC 8.0 error: “The value of ESP was not properly saved across a function call…”. The posting has over 42K views and 16 answers/comments none of which blamed the compiler as the problem. At least in my case I can show that the VS2015 compiler is at fault.
My dev and test setup is the following: I have 3 PCs all of which run Win10 version 10.0.10586. All are compiling with VS2015, but here is the difference. Two of the VS2015s have Update 2 while the other has Update 3 applied. The PC with Update 3 works, but the other two with Update 2 fail with the same error as reported in the posting above. My MFC C++ app code is exactly the same on all three PCs.
Conclusion: at least in my case for my app the compiler version (Update 2) contained a bug that broke my code. My app makes heavy use of std::packaged_task so I expect the problem was in that fairly new compiler code.
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?
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).
Here's a stripped down C++ program that produces that error. Compiled using (Microsoft Visual Studio 2003) produces the above mentioned error.
#include "stdafx.h"
char* blah(char *a){
char p[1];
strcat(p, a);
return (char*)p;
}
int main(){
std::cout << blah("a");
std::cin.get();
}
ERROR:
"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 declared with one calling convention with a function pointer declared with a different calling convention."
I had this same problem here at work. I was updating some very old code that was calling a FARPROC function pointer. If you don't know, FARPROC's are function pointers with ZERO type safety. It's the C equivalent of a typdef'd function pointer, without the compiler type checking.
So for instance, say you have a function that takes 3 parameters. You point a FARPROC to it, and then call it with 4 parameters instead of 3. The extra parameter pushed extra garbage onto the stack, and when it pops off, ESP is now different than when it started. So I solved it by removing the extra parameter to the invocation of the FARPROC function call.
Not the best answer but I just recompiled my code from scratch (rebuild in VS) and then the problem went away.