Ошибка: SafeHandle или CriticalHandle типа ZLibStreamHandle не удалось правильно освободить

Я не очень много работал с потоками, поэтому я предполагаю, что здесь, с моей стороны, где-то есть ошибка кодирования.

   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 )

2 ответа

определяется.Net Framework Managed Debug Assistant

Это не исключение, просто уведомление от MDA (Managed Debugging Assistant). Маленькие кусочки кодов, интегрированные в CLR, которые проверяют наличие общих ошибок во время выполнения. Вид, который трудно диагностировать без помощи жесткого исключения. Вы получаете уведомление MDA только при использовании отладчика. И только когда MDA включен, большинство нет.

'ReleaseHandleFailed'

MDA, который говорит, является тем, который проверяет, что SafeHandle используется должным образом. В данном конкретном случае это класс ZLibStreamHandle. Фактическая де / компрессия выполняется Zlib, библиотекой с открытым исходным кодом, которая написана на нативном коде. SafeHandles обычно используются для управления неуправляемыми ресурсами, они гарантируют, что такой ресурс будет выпущен с критическим финализатором.

Что примечательно в releaseHandleFailed Мда в том что он нормально выключен. Он должен быть включен программистами, которые пишут классы SafeHandle, как программист Microsoft, который написал ZLibStreamHandle. Так что, хотя ошибка, стоящая за этим уведомлением, вполне может встречаться, почти никто ее не замечает. Ошибки, которые никогда не диагностируются, никогда не исправляются.

не удалось правильно освободить дескриптор со значением 0x0000000000000000

Это говорит о том, что предупреждение MDA является полностью мягким. Ни один фактический неуправляемый ресурс не освобождается неправильно, и ничто не может пойти не так, базовый дескриптор равен нулю Ваша программа будет продолжать работать, когда вы нажмете F5, чтобы продолжить работу. Как и любой модульный тест, который подтвердил изменения в платформе 4.5, MDA не активны в модульных тестах.


Тем не менее, что-то пошло не так, объект ZLibStreamHandle не должен был быть создан для нулевого дескриптора. Я не вижу очевидного способа, как это можно было найти в самом классе. И, конечно же, оригинальный разработчик Microsoft тоже этого не видел:) Этот MDA обычно запускается финализатором. В данном случае это не так, оператор using (он же вызов Dispose()) вызвал его. Это необычно, я подозреваю, что вы получили этот MDA до того, как получили исключение, которое сообщило вам, что в нативном коде что-то пошло не так. Происходит, потому что оператор using генерирует блок finally, который выполняется до того, как будет сообщено об исключении. Если это верно, то нажатие F5 должно выявить истинную проблему.

В противном случае вы ничего не можете сделать с ошибкой в ​​коде фреймворка. Помимо сообщения об этом, чтобы Microsoft могла это исправить, используйте connect.microsoft.com, чтобы сообщить им об этом.

И выключите MDA, чтобы вы могли счастливо игнорировать его, как и все остальные. Отладка> Исключения> Управляемые помощники отладки> снимите флажок ReleaseHandleFailed. Если вы отметили их все, наиболее типичным способом, которым MDA включаются случайно, тогда сбросьте флажок родительского элемента.

В моем случае, просто в базе данных была пустая строка в столбце, данные которого были сжаты. И проблема возникает, когда вы заархивируете / разархивируете пустые строки, используя только SQL 2012. Это не встречается в SQL 2008/2008R2. Надеюсь это поможет.

Другие вопросы по тегам