【问题标题】:pinvokestackimbalance -- how can I fix this or turn it off?pinvokestackimbalance - 我该如何解决或关闭它?
【发布时间】:2011-03-31 05:24:27
【问题描述】:

我刚从 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


    【解决方案1】:

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

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

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

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

    欲了解更多信息,请参阅this MSDN reference

    【讨论】:

    • 谢谢!例外肯定已经停止射击。也许这也能解决我们遇到的一些长期稳定性问题。
    • 很有可能。这种特殊类型的堆栈不平衡实际上有些常见。它不会立即导致任何错误,但会慢慢消耗线程的堆栈。最终,“坏事”会发生。 CLR通常能够引发StackOverflowException,但是当堆栈已满时,using、catch 和finally 块确实使事情变得复杂。因此,从 .NET 2.0 开始,StackOverflowException 只会终止进程。
    • 更多关于互操作调用约定的信息here。
    • 非常好,在尝试将一些项目更新到 .Net 4.0 之后,这为我指明了正确的方向。将 C# 源代码中的调用约定更改为 Cdecl 后,我必须更改 *.h 和 *.c 文件以使用 '__cdecl`。
    • 谢谢!这个回应挽救了一天。就我而言,问题是由于在 Visual Studio 2010 项目中引用了 Visual C++ 8.0 (Visual Studio 2008) DLL。
    【解决方案2】:

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

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

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

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

    我还注意到,尽管计算机的功率每 12 个月翻一番,但我目前配备 1gig RAM 的计算机似乎并不比我的第一台配备 4 Meg 的 486 快。 不要担心使用 64 位代码,它不会更快或更好,因为它是建立在一个巨大的、笨重的面向对象的膨胀塔上。

    【讨论】:

    • 感谢您的提示,我会检查一下。但是,如果您运行的是只有 1 GB RAM 的 Windows 64 位操作系统,您就会遇到速度问题。您应该升级到至少 4 GB,否则您将遇到交换问题。 64 位操作系统可以在内存中而不是在磁盘中提供更多信息,并且这种更改可以产生很大的速度提高,具体取决于操作。如果你的机器没有比 486 快,可能是时候做一些病毒检查了 :)
    • 成功了,非常感谢!节省了我数小时甚至数天!
    【解决方案3】:

    要关闭它:

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

    【讨论】:

    • 从不,从,从向信使开枪。堆叠失衡迟早会吃掉你的肝脏,还有蚕豆。
    【解决方案4】:

    解决这个问题比较好解决,这里我提一些方法,可能和上面提到的一些朋友一样。我正在使用 PCSC 一个智能卡应用程序,我花了大约一周的时间,很生气,做了很多改变终于得到了解决方案。

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

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

    如果错误是因为签名不匹配,您只需点击 PInvoke.net> 插入 PInvoke 签名

    新窗口将如下所示

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

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

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

    祝编程愉快!

    【讨论】:

    • 在搜索窗口中找不到大多数 DLL。不幸的是,它看起来很整洁。
    【解决方案5】:

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

    【讨论】:

      猜你喜欢
      • 2017-10-28
      • 2015-03-23
      • 2014-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-16
      • 2021-11-27
      • 1970-01-01
      相关资源
      最近更新 更多