3

我对流的工作不多,所以我认为我这里的某个地方存在编码错误。

   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());
                }

            }

        }
    }

这是 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 )
4

2 回答 2

5

由 .Net Framework Managed Debug Assistant 识别

这不是例外,只是来自 MDA(托管调试助手)的通知。集成在 CLR 中的少量代码用于检查常见的运行时错误。没有硬异常的帮助就很难诊断的那种。只有在使用调试器时才会收到 MDA 通知。而且只有在启用 MDA 时,大多数都没有。

'释放句柄失败'

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

MDA值得注意的releaseHandleFailed是它通常是关闭的。它应该由编写 SafeHandle 类的程序员打开,例如编写 ZLibStreamHandle 的 Microsoft 程序员。因此,虽然此通知背后的错误可能很常见,但几乎没有人看到它。从未被诊断出的错误永远不会得到修复。

未能正确释放值为 0x0000000000000000 的句柄

这告诉您 MDA 警告是完全良性的。没有实际的非托管资源被不当释放,也不会出错,底层句柄为空。当您按 F5 继续运行时,您的程序将继续愉快地运行。与验证 4.5 框架中的更改的任何单元测试一样,MDA 在单元测试中不活跃。


尽管如此,还是出了点问题,不应该为空句柄创建 ZLibStreamHandle 对象。我看不出有什么明显的方法是如何在课堂上搞砸的。当然,最初的 Microsoft 开发人员也没有看到它 :) 这个 MDA 通常由终结器触发。这里不是这种情况,使用语句(又名 Dispose() 调用)触发了它。这很不寻常,我怀疑您在遇到异常之前获得了此 MDA,该异常告诉您本机代码中出现了一些问题。发生是因为using语句生成了一个 finally 块,该块在报告异常之前执行。如果这是准确的,那么按 F5 应该会揭示真正的问题。

对于框架代码中的错误,您无能为力。除了报告它以便 Microsoft 可以修复它之外,请使用 connect.microsoft.com 告诉他们有关它的信息。

并关闭 MDA,这样您就可以像其他人一样愉快地忽略它。调试 > 异常 > 托管调试助手 > 取消选中 ReleaseHandleFailed。如果您将它们全部勾选,这是意外启用 MDA 的最典型方式,然后重置父级的复选框。

于 2016-07-19T12:02:01.173 回答
2

就我而言,只是数据库在其数据被压缩的列中有空字符串。当您仅使用 SQL 2012 压缩/解压缩空字符串时,就会出现问题。在 SQL 2008/2008R2 中看不到它。希望这可以帮助。

于 2016-07-25T10:49:43.047 回答