pinvokestackimbalance —如何解决此问题或将其关闭?


76

我刚从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指令中添加一组不同的参数吗?

Answers:


145

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

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

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

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

有关更多信息,请参见此MSDN参考。


谢谢!例外肯定已经停止了。也许这将解决我们同样遇到的一些长期稳定性问题。
mmr

4
很有可能。这种特殊类型的堆栈不平衡实际上是很常见的。它不会立即导致任何错误,但是会慢慢消耗线程的堆栈。最终,“坏事”将会发生。CLR是通常就能提高StackOverflowException,但是usingcatchfinally块真正复杂的事情,当堆栈已满。因此,从.NET 2.0开始,aStackOverflowException会终止该过程。
Stephen Cleary 2010年

有关互操作调用约定的更多信息,请参见此处
德鲁·诺阿克斯

太好了,在尝试将某些项目更新到.Net 4.0之后,这为我指明了正确的方向。在将C#源代码中的调用约定更改为之后Cdecl,我不得不对我们的* .h和* .c文件进行更改,以使用'__cdecl`。
IAbstract 2012年

谢谢!这个回应挽救了一天。就我而言,此问题是由于在Visual Studio 2010项目中引用Visual C ++ 8.0(Visual Studio 2008)DLL而引起的。
Schrockwell,

45

要将其关闭:

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

3
从来没有,从来没有从来没有拍摄的使者。堆栈失衡会或早或晚与蚕豆一起吞噬您的肝脏。
汉斯·帕森特

8

更好地解决这个问题并不困难,这里我要提到一些方法,它可能与我上面提到的一些朋友相同。我正在与PCSC一起使用智能卡应用程序,我花了大约一周的时间,但由于进行了很多更改而感到气愤,最后才找到了解决方案。

对于我来说,它与我为VS2010安装的PInvoke Extension一起使用时,可以在这里http://www.red-gate.com/products/dotnet-development/pinvoke/下载

下载并安装它,关闭visual studio并再次打开,您可以在菜单栏中找到扩展名。 在此处输入图片说明

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

新窗口将如下所示 在此处输入图片说明

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

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

这解决了我的问题,您可能会遇到其他问题,例如在调用dll时需要callingConvention或需要指定其他属性。

编码愉快!


在搜索窗口中找不到大多数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个月加电一次,但我当前的RAM为1gig的计算机似乎并不比我的第一台486 Meg的486快。不必担心使用64位代码,它不会变得更快或更好,因为它是建立在庞大而笨拙的面向对象的膨胀塔上的。


1
感谢您的提示,我将对其进行检查。但是,如果您运行的Windows 64位操作系统仅具有1 GB的RAM,则将出现速度问题。您应该至少升级到4 GB,否则会遇到交换问题。64位OS提供了更多的内存信息而不是磁盘信息,并且这种改变可以大大提高速度,具体取决于操作。如果您的计算机不是比486快,可能是时候进行一些病毒检查了:)
mmr 2011年

这行得通,非常感谢!节省了我几个小时!
Alex Z

0

我试图用CallingConventionis调用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/zh-cn/library/system.runtime.interopservices.callingconvention(v=vs.110).aspx

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.