PinvokeStackImbalance 发生。抛出此异常,但我不知道错误是啥?

Posted

技术标签:

【中文标题】PinvokeStackImbalance 发生。抛出此异常,但我不知道错误是啥?【英文标题】:PinvokeStackImbalance occured. This exception is thrown but i have no idea what the error is?PinvokeStackImbalance 发生。抛出此异常,但我不知道错误是什么? 【发布时间】:2015-09-08 05:34:38 【问题描述】:

例外情况:

托管调试助手“PInvokeStackImbalance”在“D:\UI_still_in_progress\user_interface\bin\Debug\WindowsFormsApplication1.vshost.exe”中检测到问题。

基本上,我的应用程序在 C++ 中有一个后台实时进程,它与微处理器通信。我已经设置了一个 c++ dll 文件,它允许我从 c++ 应用程序和 c# UI 实时传递数据。

我的问题是,我必须创建一个有限状态机,以确保物理设备和 c++ 应用程序都在根据 UI 中发生的事情做他们应该做的事情。所以我的目标是将代表状态的简单整数从 c# 传递到 c++。

实时数据从 c++ 传递到 c#,使用以下实现没有问题:

c++ .h 文件 sn-p:

extern "C" __declspec (dllexport) int grabx();
extern "C" __declspec (dllexport) void setFSMstate(int s);

C++ .cpp 文件 sn-p:

int grabx()

    return x0;


void setFSMstate(int s)

    state = s;

c# 类

public class MyDllMethods 

    [DllImport("dllTESTER.dll")]
    public static extern int grabx();

    [DllImport("dllTESTER.dll")]
    public static extern void setFSMstate(int s);

c# 方法调用

xx = MyDllMethods.grabx();
MyDllMethods.setFSMstate(2);

grabx() 函数工作正常,我可以实时读取设备中的 x 值。当我的 UI 移动到新屏幕时,我尝试通过将 2 传递给 setFSMstate() 来更改每个应用程序中的状态。调用此方法时会引发异常。

我对 P/Invoke 还是很陌生,所以如果我遗漏了什么,请帮忙。我可能编组错了,但我确信 int 类型在 c# 和 c++ 中是相同的?

【问题讨论】:

【参考方案1】:

您遇到的问题是调用约定不匹配。调用约定指定如何将参数传递给函数,以及如何将它们的返回值传递回调用者。您的 C++ 函数是使用隐式调用约定 __cdecl 声明的,但 P/Invoke 的默认调用约定是 __stdcall

要解决此问题,您只需更改 P/Invoke 配置:

[DllImport("dllTESTER.dll", CallingConvention = CallingConvention.Cdecl)]

(您的第一个方法没有任何问题的原因是它没有任何参数——__cdecl__stdcall 以不同的方式传递参数,但它们都指定整数返回值存储在EAX 寄存器。)

【讨论】:

以上是关于PinvokeStackImbalance 发生。抛出此异常,但我不知道错误是啥?的主要内容,如果未能解决你的问题,请参考以下文章

StringBuilder 编组导致 PInvokeStackImbalance 异常

pInvokeStackImbalance 调试异常的解决办法。

C#——在有据可查的函数上检测到 PInvokeStackImbalance?

在 VB.NET 2010 中使用 GetAsyncKeyState 时的 PInvokeStackImbalance

PInvokeStackImbalance C# 调用非托管 C++ 函数

托管调试助手 "PInvokeStackImbalance":的调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。请检查 PInvoke 签名的调