错误:ZLibStreamHandle类型的SafeHandle或CriticalHandle无法正确释放

Tim*_*Tim 3 c# dispose gzipstream safehandle

我没有用过很多关于流的工作,所以我认为这里有一个编码错误.

   public static SqlBytes Compress(SqlBytes input)
    {
        byte[] data = (byte[])input.Value;
        using (MemoryStream memstream = new MemoryStream(data))
        {

            using (GZipStream zipped = new GZipStream(memstream, CompressionMode.Compress))
            {
                using (MemoryStream output = new MemoryStream()) 
                {
                    zipped.CopyTo(output);
                    return new SqlBytes(output.ToArray());
                }

            }

        }
    }
Run Code Online (Sandbox Code Playgroud)

这是SQL Server 2012 CLR中的错误:

Msg 10323, Level 16, State 49, Line 1
Invalid user code has been identified by .Net Framework Managed Debug Assistant 'releaseHandleFailed':
A SafeHandle or CriticalHandle of type 'ZLibStreamHandle' failed to properly release the handle with value 0x0000000000000000. This usually indicates that the handle was released incorrectly via another means (such as extracting the handle using DangerousGetHandle and closing it directly or building another SafeHandle around it.)
   at System.Runtime.InteropServices.SafeHandle.InternalDispose()
   at System.IO.Compression.DeflaterZLib.Dispose(Boolean disposing)
   at System.IO.Compression.DeflateStream.Dispose(Boolean disposing)
   at System.IO.Stream.Close()
   at System.IO.Compression.GZipStream.Dispose(Boolean disposing)
   at System.IO.Stream.Close()
   at UserDefinedFunctions.Compress(SqlBytes input)
   at SQLCLR_Eval(IntPtr , IntPtr , IntPtr )
Run Code Online (Sandbox Code Playgroud)

Han*_*ant 5

由.Net Framework托管调试助手识别

这不是例外,只是来自MDA(托管调试助手)的通知.CLR中集成的一小部分代码可检查常见的运行时故障.没有硬性异常的帮助很难诊断的那种.您只能在使用调试器时收到MDA通知.并且只有在启用MDA时,大多数都不是.

'releaseHandleFailed'

说出的MDA是检查正确使用SafeHandle的MDA.在这种特定情况下,它是ZLibStreamHandle类.实际的解压缩是由Zlib完成的,Zlib是一个用本机代码编写的开源库.SafeHandles通常用于管理非托管资源,它们确保使用关键终结器发布此类资源.

releaseHandleFailedMDA 值得注意的是它通常是关闭的.它应该由编写SafeHandle类的程序员打开,比如编写ZLibStreamHandle的Microsoft程序员.因此,尽管通常会遇到此通知背后的错误,但几乎没有人会看到它.从未诊断出的错误永远不会得到修复.

无法正确释放值为0x0000000000000000的句柄

这告诉你MDA警告完全是良性的.没有实际的非托管资源被不正确地释放,没有任何东西可以出错,底层句柄为空.当您按F5继续运行时,您的程序将保持愉快的开机状态.除了验证4.5框架中的更改的任何单元测试之外,MDA在单元测试中也不活跃.


然而,确实出了问题,不应该为null句柄创建ZLibStreamHandle对象.我没有看到在班级本身如何被弄糟的明显方式.当然,最初的Microsoft开发人员也没有看到它:)这个MDA通常由终结器触发.不是这里的情况,using语句(又名Dispose()调用)触发了它.这是不寻常的,我怀疑你得到这个MDA之前你得到一个异常,告诉你在本机代码中出现了问题.发生这种情况,因为using语句生成在报告异常之前执行的finally块.如果这是准确的,那么按F5应该揭示真正的问题.

关于框架代码中的错误,您无法做任何其他事情.除了报告以便Microsoft可以修复它之外,请使用connect.microsoft.com告诉他们.

并关闭MDA,以便您可以像其他人一样高兴地忽略它.Debug> Exceptions> Managed Debugging Assistants> untick ReleaseHandleFailed.如果您勾选了所有这些,这是MDA意外启用的最典型方式,则重置父级的复选框.