Weird Msc 8.0 Error: "The Value of Esp Was Not Properly Saved Across a Function Call..."

The value of ESP was not properly saved across a function call error

I finally found how to fix this problem!

Right click on your Project , Choose Properties , Go to Configuration Properties , Select C/C++ then select Code Generation .

Change Basic Run Time Check to Default.

Change Struct Member Alliance to 1 Byte (/Zp1) .

I really hope this work for you guys too.

Best Regards

ESP was not properly saved across a function call when using function pointers

Ignoring the storage in an array your code is essentially:

void (Test::*ffp)(byte*) = &fTest::FuncTest;
void* pData = (void*)ffp;
void(*func_pointer)(byte*) = (void(*) (byte*))(pData);
func_pointer(nullptr);

The type of ffp is essentially (although not exactly due to differing calling conventions) void (fTest*, byte*) which doesn't match the type of func_pointer.

The solution to this is to use std::function with with either std::bind or lambdas to convert the function signatures. e.g.:

std::vector<std::function<void(byte*)>> functions;
fTest test;
functions.push_back([=](byte* data){ test.FuncTest(data); });
functions.front()(nullptr);

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

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.

Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call

Because you're using multiple inheritance, the vftable pointer to what is expected to be a MyInterface* is actually a pointer to a QGraphicsLineItem vftable.

A dynamic_cast would solve the issue because it will return the correct vftable

MyInterface* mInterface = dynamic_cast<MyInterface*>(item);

A simple example:

class A
{
public:
virtual void foo() = 0;
};

class B
{
public:
virtual void goo() {};
};

class C : public B, public A
{
public:
virtual void foo() {};
};

//....

B* c = new C; // c is at 0x00a97c78
A* a = (A*)c; // a is at 0x00a97c78 (vftable pointer of B)
A* a1 = dynamic_cast<A*>(c); // a1 is at 0x00a97c7c (vftable pointer of A)

Value of ESP was not properly saved

This function uses the stdcall calling convention and takes an argument, but does not free the space the argument occupies, so the stack will be imbalanced after it returns (the caller won't adjust the stack to get rid of the arguments, because for calling an stcall function that is not necessary).

Change ret to ret 4.



Related Topics



Leave a reply



Submit