“运行时检查失败 #0 - ESP 的值未在函数调用中正确保存”从 C++ 代码成功 C# 回调后
Posted
技术标签:
【中文标题】“运行时检查失败 #0 - ESP 的值未在函数调用中正确保存”从 C++ 代码成功 C# 回调后【英文标题】:"Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call" after successful C# callback from the C++ code 【发布时间】:2010-11-30 17:09:24 【问题描述】:我正在制作一个使用 GameSpy C 代码(GP 部分)的 C# 应用程序。 C 代码成功调用回调(即 C# 代码),但在回调完成后我立即收到此错误Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call
。我用 C 代码制作了一个 DLL,如下所示:
// GPCallback
/////////////
__declspec(dllexport) typedef void (* GPCallback)(
GPConnection * connection,
void * arg,
void * param
);
// gpConnect
////////////
__declspec(dllexport) GPResult gpConnect
(
GPConnection * connection,
const gsi_char nick[GP_NICK_LEN],
const gsi_char email[GP_EMAIL_LEN],
const gsi_char password[GP_PASSWORD_LEN],
GPEnum firewall,
GPEnum blocking,
GPCallback callback,
void * param
);
C# 是这样称呼它的:
unsafe public delegate void GPCallback(
GPConnection * connection,
//GPConnectResponseArg arg,
IntPtr arg,
IntPtr param
);
[DllImport("saketestd.dll")]
unsafe static extern GPResult gpConnect(
GPConnection * connection,
gsi_char nick,
gsi_char email,
gsi_char password,
GPEnum firewall,
GPEnum blocking,
GPCallback callback,
IntPtr param
);
unsafe public bool gpConnectE()
bool ret = false;
try
GPResult res;
debug.AddLine(this.getMethodName() + ": " + "connection before connect: " + connection.ToString("x"));
fixed (int* pconn = &connection)
res = gpConnect(
pconn,
this.NICK,
this.EMAIL,
this.PASSWORD,
GPEnum.GP_NO_FIREWALL,
GPEnum.GP_BLOCKING,
new GPCallback(this.ConnectResponse),
IntPtr.Zero
);
debug.AddLine(this.getMethodName() + ": " + "connection after connect: " + connection.ToString("x"));
if (res != GPResult.GP_NO_ERROR)
debug.AddLine(this.getMethodName() + ": " + "failed: " + res);
else
debug.AddLine(this.getMethodName() + ": " + "OK");
ret = true;
catch (Exception ex)
debug.Text += ex.ToString();
return ret;
unsafe public void ConnectResponse(
GPConnection * connection,
//GPConnectResponseArg arg,
IntPtr argPtr,
IntPtr param
)
debug.AddLine(this.getMethodName() + " called with connection: " + (*connection).ToString("x"));
GPConnectResponseArg arg;
arg = (GPConnectResponseArg)Marshal.PtrToStructure(argPtr, typeof(GPConnectResponseArg));
if (arg.result == GPResult.GP_NO_ERROR)
debug.AddLine(this.getMethodName() + ": Connected to GP");
this.profileid = arg.profile;
else
debug.AddLine(this.getMethodName() + ": failed");
debug.AddLine(this.getMethodName() + ": result: " + arg.result);
debug.AddLine(this.getMethodName() + ": profile: " + arg.profile);
debug.AddLine(this.getMethodName() + ": uniquenick: " + arg.uniquenick);
我认为我需要清除回调中的堆栈或更改 DLL 中的调用约定(这可能吗?)。还有其他想法吗?
【问题讨论】:
【参考方案1】:我自己出乎意料地解决了问题(经过 5 小时的谷歌搜索)。 我已经怀疑是错误的调用约定,但我不知道如何正确切换它。 我已经按照此处的建议在 C 代码中进行了更改 (http://computerarts.com.cn/dotnet-tech/1691/):
// GPCallback
/////////////
//__declspec(dllexport) typedef void (* GPCallback)(
//typedef __declspec(dllexport) void (* GPCallback)(
typedef void (_stdcall * GPCallback)(
GPConnection * connection,
void * arg,
void * param
);
【讨论】:
【参考方案2】:检查您正在使用的调用约定。
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
参考其他相关问题:Callback from C function - crash
【讨论】:
以上是关于“运行时检查失败 #0 - ESP 的值未在函数调用中正确保存”从 C++ 代码成功 C# 回调后的主要内容,如果未能解决你的问题,请参考以下文章