pinvokestackimbalance - 如何修复此问题或将其关闭?

问题描述 投票:68回答:5

我刚从vs2008切换到vs2010。完全相同的解决方案,除了现在每次调用C ++ dll都会产生'pinvokestackimbalance'异常。

此异常在2008年不会被触发。我可以完全访问C ++ dll和调用应用程序。 pinvoke似乎没有任何问题,但是这个问题使调试其他问题变得不可能; 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指令中添加一组不同的参数吗?

c# c++ visual-studio-2010 visual-studio pinvoke
5个回答
131
投票

首先,要了解代码是错误的(并且始终存在)。 “pInvokeStackImbalance”本身不是一个例外,而是一个托管调试助手。它默认在VS2008中关闭,但是很多人没有打开它,所以默认情况下它在VS2010中启用。 MDA不在发布模式下运行,因此如果您为发布版本构建它将不会触发。

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

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

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

有关更多信息,请参阅this MSDN reference


38
投票

要关闭它:

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

8
投票

更好地解决这个问题在这里并不困难我提到了一些方法,它可能与我上面提到的一些朋友一样。我正在使用PCSC一个智能卡应用程序我花了大约一个星期,生气了很多变化终于得到了解决方案。

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

下载并安装它,关闭visual studio并再次打开,您可以在菜单栏找到扩展名。

如果错误是由于签名不匹配,您只需单击PInvoke.net>插入PInvoke签名

新窗口将如下所示

输入dll的名称并单击搜索,您可以在搜索结果窗口中看到该dll的所有功能,单击该功能,您将获得该特定功能的签名。

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

这解决了我的问题,你可能有不同的问题,如callConvention或导入DLL时需要指定的其他属性。

快乐的编码很好!


3
投票

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

不要以为你的Dll有什么问题,没有。

更改您的VS设置以生成这样的X86代码(C#的Express版本)

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

我还注意到,即使计算机每12个月的功率增加一倍,我目前的计算机内存为1gig,似乎并不比我的第一台486的4兆。不要担心使用64位代码,它不会更快或更好,因为它建立在一个庞大的,笨重的面向对象的膨胀塔上。


0
投票

我试图用CallingConvention调用dll是ThisCall,它对我有用。这是我的代码使用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

© www.soinside.com 2019 - 2024. All rights reserved.