PinvokestackBalance ——我怎样才能修复或者关闭它?

我刚从2008版切换到2010版。完全相同的解决方案,只是现在对 C + + dll 的每一次调用都会产生一个“ pinvokestackBalance”异常。

这个例外在2008年不会被解雇。我可以完全访问 C + + dll 和调用应用程序。Pcall 似乎没有任何问题,但是这个问题使得调试其他问题变得不可能; IDE 不断停下来告诉我这些事情。

例如,下面是 C # 签名:

    [DllImport("ImageOperations.dll")]
static extern void FasterFunction(
[MarshalAs(UnmanagedType.LPArray)]ushort[] inImage, //IntPtr inImage,
[MarshalAs(UnmanagedType.LPArray)]byte[] outImage, //IntPtr outImage,
int inTotalSize, int inWindow, int inLevel);

下面是它在 C + + 方面的样子:

#ifdef OPERATIONS_EXPORTS
#define OPERATIONS_API __declspec(dllexport)
#else
#define OPERATIONS_API __declspec(dllimport)
#endif
extern "C" {




OPERATIONS_API void __cdecl FasterFunction(unsigned short* inArray,
unsigned char* outRemappedImage,
int inTotalSize,
int inWindow, int inLevel);


}

Vs2010和 vs2008之间有什么不同,会导致抛出这些异常?我是否应该向 DllImport 指令添加一组不同的参数?

76701 次浏览

首先,要明白代码是错误的(并且一直都是错误的)。“ pInvokeStackImBalance”本身并不是一个异常,而是一个托管调试助手。它在 VS2008中是默认关闭的,但是很多人没有打开它,所以在 VS2010中它是默认打开的。MDA 不在发布模式下运行,因此如果您为发布而构建,它就不会触发。

在您的情况下,调用约定是不正确的。DllImport默认为 CallingConvention.WinApi,这与 x86桌面代码的 CallingConvention.StdCall相同。应该是 CallingConvention.Cdecl

这可以通过将 [DllImport("ImageOperations.dll")]行编辑为:

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

有关更多信息,请参见 这个 MSDN 参考

我在使用 VS2010时也遇到了这个问题。 它是什么: VisualStudio 默认为“ any CPU”的64位代码。 当调用外部 Dlls 时,指向变量(例如字符串)的指针现在变成了64位,而所有可靠和受信任的 Dlls 都使用32位指针。

不要以为你的 DLL 有什么问题,其实没有。

更改 VS 设置以生成如下 X86代码(C # 的 Express 版本)

  1. 点击工具-> 选项。
  2. 在“选项”对话框的左下角,选中“显示所有设置”框。
  3. 在左侧的树形视图中,选择“ Projects and Solutions”。
  4. 在右边的选项中,选中“显示高级构建配置”的复选框
  5. 单击 OK。
  6. 转到 Build-> Configuration Manager..。
  7. 在项目旁边的 Platform 列中,单击组合框并选择“”。
  8. 在“新平台”设置中,选择“ x86”。
  9. 单击 OK。
  10. 点击关闭。

我还注意到,尽管每12个月电脑的容量就会翻一番,但是我现在使用的1G 内存的电脑似乎并不比我第一台4864M 的电脑快。 不要担心使用64位代码,它不会更快或更好,因为它是建立在一个巨大的笨重的面向对象的臃肿塔。

关掉它:

  1. CTRL + ALT + E
  2. 在“托管调试助手”下取消选中 PInvokeStackImBalance。

更好地解决这个问题并不困难,这里我提到了一些方法,它可能与我上面提到的一些朋友相同。我和 PCSC 一起工作一个智能卡应用程序我花了一个星期左右,生气做了很多改变,最终得到了解决方案。

对我来说,它的工作与 PInvoke 扩展,我安装了 VS2010你可以在这里下载 http://www.red-gate.com/products/dotnet-development/pinvoke/

下载并安装它,关闭视觉工作室,再次打开,你可以在菜单栏找到扩展。 enter image description here

如果错误是因为签名不匹配,只需单击 PInvoke.net > Insert PInvoke Signature

新窗口将如下所示 enter image description here

输入 dll 的名称并点击搜索你可以在搜索结果窗口中看到该 dll 的所有函数,点击该函数你将得到该特定函数的签名。

使用该签名,您需要根据该签名修改您的程序,主要是数据类型。

这解决了我的问题,您可能会遇到不同的问题,比如调用 Convention 或者在导入 dll 时需要指定的其他属性。

编码愉快!

我试图调用 dll 与 CallingConventionThisCall,它为我工作。以下是使用 BLOB MS Sql Server 的代码。

[DllImport("sqlncli11.dll", SetLastError = true, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.ThisCall)]
private static extern SafeFileHandle OpenSqlFilestream(
string FilestreamPath,
UInt32 DesiredAccess,
UInt32 OpenOptions,
byte[] FilestreamTransactionContext,
UInt32 FilestreamTransactionContextLength,
Int64 AllocationSize);

更多信息: https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.callingconvention(v=vs.110).aspx