ESP Error when I call an API function? - c++

platform : win32 , language : c++
I get this error when I call an imported function I declared:
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.
And this is the code I used:
int LoadSongFromFile(int module);
typedef int (CALLBACK* loadSongT)(LPCTSTR);
//...
HINSTANCE dllHandle = NULL;
loadSongT loadSongPtr = NULL;
dllHandle = LoadLibrary(L"miniFMOD.dll");
loadSongPtr = (loadSongT)GetProcAddress(dllHandle,"SongLoadFromFile");
int songHandle = loadSongPtr(L"C:\b.xm");
The function I'm trying to call is SongLoadFromFile which requires one argument (in C# it is string so I assume its LPCTSTR in C++) and returns an int value.
Can somebody check what have I done wrong?
P.S. songHandle gets a weird negative value of -858993460
This is how I can call that function from C# :
[DllImport("MiniFMOD.dll")] public static extern int SongLoadFromFile(string name);
P.S. 2 : Using *typedef int (__cdecl loadSongT)(char);* doesn't return an error but songHandle comes up as 0.
miniFMOD.dll is an unmanaged library

I think the other people are misunderstanding the question. It seems to me that minifmod.dll is a native library that exports a function named SongLoadFromFile. The existing code that calls this is managed code (C#) that uses DllImport to call the function in the native DLL. From what little information I could gather by a few Google searches, it looks as though it should be declared as follows:
typedef int (__cdecl * SongLoadFromFileT)(const char*);
Importantly, it is __cdecl calling convention and it takes an ANSI string instead of a Unicode string.
As an aside, I find it strange that I can't find ANYTHING on minifmod.dll other than a few forum posts on a Russian website and some SO questions from this guy. The only "legitimate" information I can find on minifmod is a small static library with similar functionality. I wonder if minifmod.dll is some kind of commercialized version of the static library; at least that would explain why there is not much public documentation about it.
Ah, I found it; it is a Delph port of minifmod (http://www.cobans.net/minifmod.php).

You need to make sure to specify the right calling convention in your function pointer prototype ('CALLBACK' might be the wrong choice).

The calling code uses the calling convention not matching that of the function being called. See this very similar question. You need to open the header defining that function (should come with the library you try to use), look the convention up and change your function pointer declaartion accordingly.

Related

c++ LoadLibrary() and GetProcAddress

I have a DLL I was handed down by a device manufacturer.
I can effortlessly call all its functions from a MS Console application (not from Qt or C++ Builder) but not from an MFC/WinAPI application? In an effort to work around the problem, I'm exploring the LoadLibrary() route. I am experimenting with this code, in VS2019 :
HINSTANCE hInstance = LoadLibrary(L"DEVICE.dll");
int(*fnDLLFuncAddress)(void) = (int(*)(void))GetProcAddress(hInstance2, "Device_RegisterDeviceEventHandler");
I have the impression that the code is working since this is the fnDLLFunAddress content :
fnDLLFuncAddress = DEVICE.dll!0x00007ffa66adda20 (load symbols for additional information)
Two questions, if I may. First, where would I look for "load symbols for additional information"? And the second, less obvious, is, once I have the Function address, in the form of a pointer, do I simply use the explicitely linked function name in lieu of the original function call to the DLL?
To start the program, I need to launch the following Event Handler, defined this way :
DEVICE_ERROR_TYPES __stdcall FPtr_Device_RegisterDeviceEventHandler(const FPtr_DeviceEventHandler inHandler);
In main(), the way I'm expected to launch the DeviceHandler is with this call :
deviceError = fnDLLFuncAddress(EventNotice);
Where "deviceError" is defined in DEVICE_ERROR_TYPES enum.
The EventNotice function is defined this way :
void EventNotice(EventCode outEventCode, uint32 outRAWDataCount, DEVICE_ERROR_TYPES outError);
When I try to execute the call, the compiler complains with E0140 "Too many arguments in function call" and E0513 "a value of type "int" cannot be assigned to an entity of type "DEVICE_ERROR_TYPES".
My intuition tells me I should try supplying the "EventNotice" function address in the function call? Is it simply a matter of "dereferencing" the function name like "*EventNotice"?
If this was to work, I guess I'd still have to resolve the "incompatible" return type of the RegisterDeviceHandler call?
Any help is appreciated.
=== additional note ===================
The reason I'm having difficulty, I think, is because I am unable to replicate the original "RegisterDeviceHandler" function prototype?
With GetProAddress(), I'm able to get a pointer to the function address in the DLL but that does not give me the corresponding "function declaration"?

“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.

Writing a Delphi DLL linked in from C++ Application: Access to C++ Interface Member Functions creates Access Violation

I need to write a DLL (in Delphi 2009) that is to be linked into a third party application written in MS VC++. The concept is very much that of a plugin system, which means that the application runs perfectly well without the DLL, and loads it when it is present.
Upon certain events, the application calls functions that the DLL exports. Documentation has a list of defined functions, and the so called SDK provides some sample code, of course also in C++. I do not have access to the source code of the application itself.
Following is a somewhat lengthy introduction together with some code examples. The question (that will be asked again at the bottom of this post) is: How do I have to implement the applications C++ classes, passed as pointers to interfaces, in the Delphi DLL? I've already read a couple of threads on stackoverflow and other sources, but most of them deal with modifying both ends (C++ applicaton and Delphi DLL), which is not an option. So, what I'm looking for is someone who can assist in translating the C++ DLL code to Delphi DLL code.
The called functions typically receive some parameters (mostly TCHAR*, int and some ENUMs) and have a return value of type HRESULT. Some of them do also have a parameter that is described as a pointer to a "COM-like interface", intended to make it possible to call member functions defined inside the application. During translation, I have simply prepended the types with a 'T' and declared the correspondind types in a seperate unit (TCHAR* becomes PTCHAR and is defined as PTCHAR = PAnsiChar. That makes it easy to replace the types, should it prove necessary).
Currently, the DLL functions are already called by the application and the code in the DLL has full access to the "standard" parameters like Strings or Integers. Return values are passed back to the application, so reckon that the implementation of the export functions is correct. On of the shorter examples (that works in the Delphi implementation):
// C++ function defined in the SDK
DLLAPI int FPHOOK_OnStartFlowInstance(const TCHAR* strSvcAppName,
const TCHAR* strAppName,
const FLOW_SECTION_TYPE eSectionType,
IIFlowContext* pContext)
{
return 0;
}
// Delphi translation of the same function
function FPHOOK_OnStartFlowInstance( const strSvcAppName : PTCHAR;
const strAppName : PTCHAR;
const eSectionType : TFLOW_SECTION_TYPE;
pContext : PIIFlowContext) : Int; stdcall;
begin
dbg('ENTER FPHOOK_OnStartFlowInstance: strSvcAppName = ''%s'', strAppName = ''%s''',[String(strSvcAppName),String(strAppName)]);
result := 0;
end;
Now, the problem is that I need to call one of the member functions. Here is the definition of the class (C++) resp. the interface (Delphi). I've left out most of the functions just to save space, but will gladly provide more source code if helpful.
// (shortened) class definition from C++
class IIFlowContext : virtual public CIUnknown
{
// Operation
public:
virtual HRESULT getContextID(/*[out]*/unsigned short* pContextId) = 0;
virtual HRESULT cleanExecutionState() = 0;
/* skipped some other 'virtual HRESULT ...' */
};
// (shortened) interface declaration from Delphi
type IIFlowContext = Interface(IUnknown)
function getContextID(pContextId : Punsigned_short) : HRESULT; stdcall;
function cleanExecutionState : HRESULT; stdcall;
// skipped some other 'function ...'
end;
If I now try to access one of the member functions:
function FPHOOK_OnStartFlowInstance( ...,pContext : PIIFlowContext) : Int; stdcall;
var fphookResult : HRESULT;
begin
try
fphookResult := pContext.cleanExecutionState;
except On E: Exception do
dbg('FPHOOK_OnStartFlowInstance, pContext.cleanExecutionState: %s::%s',[E.ClassName,E.Message]);
end;
result := 0;
end;
an EAccessViolation error is caught by the except block and written to the debug log. I've already tried different conventions (not sure if 'convention' is the correct term here) like cdecl or safecall instead of stdcall, all with the same result.
This is where I currently have no clue at all where to look at... I've never been a C++ (or even C) programmer, so my translation to Delphi might well be wrong. Maybe there's some other point I'm missing.
Anyway, I'd be glad if someone with a little (or much) more experience would give me some hints.
Thanks in advance
Patrick
// 2010-11-05: What I extracted from the comments, the answers and the comments to the answers
Remko's suggestion to define the parameter as
var pContext : IIFlowContext;
gives almost the same outcome as my initial attempt as
pContext : PIIFlowContext;
The exception ist thrown in both cases, but the content of the variable is different. More information is given below where I've listed the different test cases.
Barry mentioned that Interfaces in Delphi (opposite to C++) already are pointers. While C++ therefore needs to pass a pointer to the class (aka pass as reference), Delphi already expects a reference to the class. The parameter should thus be declared as
pContext : IIFlowContext;
That is, not as a pointer to the interface, nor with a var modifier.
I ran the following three test cases, all of which had a debug break point at the very first instruction on the function exported by the dll:
1) declare the parameter as a pointer to the interface
pContext : PIIFlowContext;
Outcome: According to the debugger, pContext contains a pointer to memory address $EF83B8. Calling one of the interfaces methods leads to a jump to memory address $560004C2t and throws an EAccessViolation exception.
2) declare the parameter as a reference to the Interface
var pContext : IIFlowContext;
Outcome: The debugger shows the content of pContext as "Pointer($4592DC) as IIFlowContext". Calling the interfaces method leads to a jump to the same memory address $560004C2, which then throws the same execption.
3) declare the parameter as the Interface itself (without modifier)
pContext : IIFlowContext;
Outcome: The exported dll function does not even get called. An EAccessViolation is thrown (and caught by the debugger) before the jump into the dll function occurs.
From the above I conclude that it shouldn't be to much of a difference wether the parameter is declared as var pContext : IIFlowContext or pContext : PIIFlowContext, but it is a noticable difference if it's declared as pContext : IIFlowContext.
As requested, here's the output of the debuggers dissasembly view. In the comments I've noted the values of the registers after the execution of the operation to their left:
SystemHook.pas.180: fcnRslt := pContext.cleanExecutionState;
028A3065 8B4514 mov eax,[ebp+$14] // EAX now = $00EF83D0
028A3068 8B00 mov eax,[eax] // EAX now = $004592DC
028A306A 50 push eax
028A306B 8B00 mov eax,[eax] // EAX now = $0041DE86
028A306D FF5010 call dword ptr [eax+$10] // <-- Throws Exception, EAX+$10 contains $560004C2
028A3070 59 pop ecx
028A3071 8BD8 mov ebx,eax
The disassembly is exactly the same, no matter wether the parameter is a pointer to the interface or a var reference.
Is there anything else I should provide?
One additional question that came to my mind...
In the original header file from the SDK, the class is defined as
class IIFlowContext : virtual public CIUnknown
CIUnknown, in turn, is defined in another header file (win_unknown.h) as
class CIUnknown
{
// Operation
public:
virtual HRESULT QueryInterface(REFIID iid, void ** ppvObject) = 0;
virtual unsigned long AddRef(void) = 0;
virtual unsigned long Release(void) = 0;
static bool IsEqualIID(REFIID iid1, REFIID iid2)
{
if (memcmp(&iid1, &iid2, sizeof(IID)) == 0)
return true;
return false;
}
};
Is it OK to use IUnknown as base for the Delphi interfaces? I guess not, because as far as I know, IUnknown does not implement IsEqualIID and so there would be a shift in the VMT. But, how would I implement this in Delphi? Is C++ static the same as Delphi class function?
// 2010-11-18: Some Updates
Unfortunately, I've not yet found a way to get it working. One thing that indeed changed the behaviour was passing the interface reference as
const pContext : IIFlowContext;
As Barry stated, this inhibits delphi from "automagically" calling _AddRef() on the interface. This way, I was able to initiate and debug a call to member functions of the Interface. Now I can follow the execution quite some time and can even see some calls into the windows API (e.g. CriticalSections), but at some time it still throws an EAccessViolation Error.
Currently I have no further ideas. I think I will try to get hands on a MSVC++ compiler so that I can build the DLL like recommended by the SDK. If that works then maybe using C++ to create a wrapper around by Delphi code will be the solution.
Anyway, thanks a lot for your help so far! Any additional input will be very much appreciated, though.
Based on your most recent comment, I think I know what's going on; and I should have spotted it sooner.
IIFlowContext on the C++ side is a class; IIFlowContext* pContext is passing a pointer to the class, which is how COM-style interfaces are represented in C++.
But Delphi interfaces are already pointers; the indirection is assumed, as Delphi classes are never passed around by value, like C++ classes are. You should use IIFlowContext directly, no var or const modifier, in the Delphi entrypoint.
There may still be a problem with the interface method declaration; it'll be clearer with more info: see my latest comment to your question.
My translation would be:
function FPHOOK_OnStartFlowInstance( const strSvcAppName : TCHAR;
const strAppName : TCHAR;
const eSectionType : TFLOW_SECTION_TYPE;
var pContext : IIFlowContext) : Int; stdcall;
PS: how did you define TCHAR is it Ansi or Unicode/Wide ?

Can't use DLL (written in C++) in Delphi: The procedure entry point could not be located

I've compiled a DLL in Visual Studio (the source code is in C++, which I barely understand). Here's a piece of Scraper.h:
struct SWin
{
char title[512];
HWND hwnd;
};
SCRAPER_API bool ScraperGetWinList(SWin winList[100]);
Now I'm trying to use the above function in my Delphi application:
type
tWin = record
title: String;
hwnd: HWND;
end;
function ScraperGetWinList(var WinList: Array of tWin): Boolean; external 'Scraper.dll';
var
myWinList: Array [1..100] of tWin;
procedure TMainForm.GetWinListButtonClick(Sender: TObject);
begin
ScraperGetWinList(myWinList);
...
The project doesn't compile, and I get the following message: The procedure entry point ScraperGetWinList could not be located in the dynamic link library: Scraper.dll.
What am I doing wrong?
From my Linux experience, I'd say that you've encountered so-called "name-mangling" issue. The entry point of your procedure is not called "ScraperGetWinList", but something like "_ZN18ScraperGetWinListEpN4SWin".
The thing is that, Unlike in C, in C++ language the name of entry point is not the same as the function name. No wonder: assume, you have a set of overloaded functions; they should have different entry points in your DLL. That's where name mangling comes into play.
The most common solution to this problem is to define interface of your library in such a way that it will use C calling convention. No name mangling will happen with the interface functions then.
Note that you don't have to write the whole library in C, you only should declare functions for them to emit C-like entry points.
Usually it's written like this:
extern "C" {
SCRAPER_API bool ScraperGetWinList(SWin winList[100]);
// More functions
}
Recompile your library and use it in Delphi without problems.
Note, that you should also adjust calling conventions (stdcall or cdecl) for them to match in your C++ header and Delphi code. However, that's best explained in another question.
Name mangling is most likely the problem. Name mangling is usually done is C++ code,
and when writing a DLL in C++ that should be used by code in an other langauge,
you should use the Extern "C" construction as Pavel Shved already suggested.
When using DLLs, especially when writtin in other languages, you should also keep
an eye on calling conventions. I suggest that you specify in both delphi and c++ to use the stdcall calling convenstion. This is the calling convention also used by the windows api, so it guarantees the best interoperatability between different compilers.
This would mean
extern "C" {
SCRAPER_API __stdcall bool ScraperGetWinList(SWin winList[100]);
}
and
function ScraperGetWinList(var WinList: Array of tWin): Boolean; external 'Scraper.dll';
But that's not all, the stdcall calling convention has an impact on the name mangling, and it would turn out to be something like _ScraperGetWinList#4 (Where 4 is the size of the parameter, where an array would have a pointer to the first element, so 4 bytes)
To confirm the correct symbols to use, I suggest Dependency Walker
( http://www.dependencywalker.com/ ) this program shows that exactly the function names are exported by the dll. Having confirmed the name to be '_ScraperGetWinList#4' then you add this in delpgi like this:
function ScraperGetWinList(var WinList: Array of tWin): Boolean; external 'Scraper.dll' name '_ScraperGetWinList#4';
Have you actually exported the entry point function in the c++ code? This really stumped me the first time I compiled a C++ dll in Visual Studio for use in a dotnet app.
For example, I needed to expose a print driver in unmanaged code so some other developers could access it in VB.net. This is what I did.
In foo.cpp:
extern "c" {
___declspec(dllexport) bool FooBar()
{
// Call some code on my cpp objects to implement foobar
}
}
Then in a file called foo.def:
LIBRARY "mylib"
EXPORTS
FooBar
AnyOtherFunctionsItExports
This is how I got it to work. I might not be doing things the best possiable way. I am a little light on C++ experience and also mainly don't work on windows.

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.