pinvokestack失衡MDA警告以及如何关闭或修复它

本文关键字:何关闭 失衡 MDA 警告 pinvokestack | 更新日期: 2023-09-27 17:50:25

    [DllImport( "zlib32" )]
    private static extern ZLibError compress2( 
                byte[] dest,
                ref int destLength, 
                byte[] source, 
                int sourceLength, 
                ZLibQuality quality 
            );
每次调用

时,我都会得到一个MDA警告,告诉我堆栈不平衡,这是调试的噩梦。我想要么关闭这个警告,要么修复这个问题

pinvokestack失衡MDA警告以及如何关闭或修复它

这个MDA会告诉您,您正在为PInvoke调用使用的参数类型有问题。一般来说,关闭是一个非常糟糕的主意,因为它会警告代码中的问题,并且不平衡的堆栈会导致将来的错误(有时很难找到)。

通常,常见的错误是选择非托管类型与托管类型匹配。

在您的情况下,原始定义(我看了看zlib125.zip):

ZEXTERN int ZEXPORT compress2 OF((Bytef *dest,   uLongf *destLen,
                                  const Bytef *source, uLong sourceLen,
                                  int level)); 

,可以翻译为如果库被编译为64位支持unsigned long:

static int compress2(
    byte[] dest,
    ref ulong destLength,
    byte[] source,
    ulong sourceLength,
    int level)

确保ZLibQuality枚举基于int。可能,您的错误是使用int而不是ulong两个长度。

正如David Heffernan所说,还有很多其他原因无法找到确切的一个,如果你仍然想知道,请给我们一个实际用于开发的库的链接。

  • 使用Visual c++传统编译原始库将导致您只支持32位库,因此您提供的原始定义是有效的,除非ZLibQuality枚举不是基于int

  • 也许您尝试使用为其他调用约定编译的库,例如cdecl而不是stdcall

  • 也许你尝试使用修改的库,其中compress2函数需要额外的参数。

当我们看到你正在使用的确切的库时,我们可以发现哪里有问题。

longunsigned long通常在Windows下为32位,分别映射到intuint。由于您在原始声明中遇到麻烦,我假设您可能正在使用具有64位支持的特定库。感谢David Heffernan给我指出来,让我的注意更清晰。

您可以使用以下资源作为参考:

  • .NET开发人员的wiki - PInvoke.net主要是一个wiki,允许开发人员查找,编辑和添加PInvoke*签名,用户定义类型,以及与从托管代码调用Win32和其他非托管api相关的任何其他信息

  • PInvoke Interop Assistant

/顺便

为什么你要用你自己的实现和library的self绑定?你可以使用:

  • DotNetZip -在c#, VB,任何。net语言中压缩和解压缩- DotNetZip是一个易于使用,快速,免费的类库和工具集,用于操作Zip文件或文件夹。Zip和Unzip很容易:使用DotNetZip,用VB、c#(任何。net语言)编写的。net应用程序可以很容易地创建、读取、提取或更新Zip文件。

  • 或准备使用7-zip绑定:SevenZipSharp -托管的7-zip库,用c#编写,提供数据(自)提取和压缩(所有7-zip格式都支持)。它包装7z.dll或任何兼容的一个,并使用LZMA SDK。

堆栈不平衡是因为调用约定不匹配或函数声明不匹配。如果zlib32使用stdcall调用约定,我会感到非常惊讶。当然使用cdecl。在给出更确切的建议之前,我想看看你对该函数的c++声明。

保留警告,因为它会发现代码中的错误,并修复不匹配,无论它们是什么

这里可能有一个真正的问题,但我通常不得不不时禁用所有托管调试助手,因为其中一些神奇地启用了。一定要检查Debug | Exceptions节点,然后展开 Managed Debugging Assistants,并确保所有这些都被禁用。

EDIT:您将有更好的运气替换p/Invoke与您为compress2创建的c++/CLI包装器