Должны ли маршал. Freehglobal быть помещенным в наконец -то блок, чтобы убедиться, что ресурсы утилизированы?

StackOverflow https://stackoverflow.com/questions/3525932

Вопрос

У меня есть следующий блок кода:

IntPtr unmanagedPointer = Marshal.AllocHGlobal(buffer.Length);
Marshal.Copy(buffer, 0, unmanagedPointer, buffer.Length);
SomeCommandThatCanThrowAnException();
Marshal.FreeHGlobal(unmanagedPointer);

Если блок будет заверен в попытке, а команда Freehglobal будет помещена в наконец -то блок. (В случае, если средняя команда бросает исключение).

Кажется, имеет смысл, который, наконец, предотвратит утечки памяти в этом случае, однако из примеров, которые я нашел в Интернете, наконец, не используется. Возможно, ресурсы в любом случае автоматически утилизируются (хотя они и неуправляются).

Это было полезно?

Решение

Нена управления памятью, выделенная Marshal.allochglobal, не выпускается автоматически.

Так что поместите маршал. Freehglobal в finally Блок действительно хорошая идея:

IntPtr unmanagedPointer = Marshal.AllocHGlobal(buffer.Length);
try
{
    Marshal.Copy(buffer, 0, unmanagedPointer, buffer.Length);
    SomeCommandThatCanThrowAnException();
}
finally
{
    Marshal.FreeHGlobal(unmanagedPointer);
}

Примеры, которые вы обнаружили, вероятно, пропускают обработку ошибок для краткости.


Если вы выделяете неуправляемую память для долговременных целей (то есть не освобождаете ее в пределах того же метода), вы можете быть заинтересованы в завершении указателя в объект, который происходит от SafeHandle (такие как Safebuffer).

SafeHandle реализует идентифицируемый шаблон, поэтому неуправляемая память будет освобождена, когда вы утилизируете объект или когда сборщик мусора собирает объект. SafeHandle также вытекает из класса CriticalFinalizerObject, что означает, что он получит специальную обработку от CLR, чтобы убедиться, что память действительно освобождена.

class HGlobal : SafeBuffer
{
    public HGlobal(int cb)
        : base(true)
    {
        this.SetHandle(Marshal.AllocHGlobal(cb));
        this.Initialize((ulong)cb);
    }

    protected override bool ReleaseHandle()
    {
        Marshal.FreeHGlobal(this.handle);
        return true;
    }
}

Пример:

using (var h = new HGlobal(buffer.Length))
{
    h.WriteArray(0, buffer, 0, buffer.Length);
}

Примечание: Safebuffer - это довольно зверь, поэтому рекомендуется осторожность.

ПРИМЕЧАНИЕ 2: SafeHandles хорошо работают с P/Invoke и устраните необходимость полностью передать IntPTR.

Safebuffers предназначены для безопасной манипулирования неуправляемой памятью от C#, поэтому в зависимости от того, что вы делаете (выделяя неуправляемую память для использования с P/Invoke, или манипулируя неуправляемой памятью из C#), вы должны выбрать SafeHandle или SafeBuffer в качестве базового класса соответствующим образом.

Другие советы

Абсолютно. Это никогда Выпускается автоматически, это неуправляемая память.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top