Если класс имеет свойство, которое содержит неуправляемые ресурсы. Как убедиться, что утечка памяти при использовании классакак обеспечить утечку памяти в следующем случае
Class A
{
B {get; set;}
}
В содержит неуправляемые ресурсы.
Если класс имеет свойство, которое содержит неуправляемые ресурсы. Как убедиться, что утечка памяти при использовании классакак обеспечить утечку памяти в следующем случае
Class A
{
B {get; set;}
}
В содержит неуправляемые ресурсы.
Реализовать IDisposable
и очистить ваши неуправляемые ресурсы путем вызова Dispose()
, предпочтительно поместить вызов Dispose
в finally
заявлении, так что вы очистки ресурсов даже в случае исключения.
C# имеет ключевое слово using
, которое можно использовать, чтобы удостовериться, что вызывается метод Dispose
, даже если выбрано исключение.
EDIT: Включенный вызов GC.SuppressFinalize и реализации финализатора в ответ Ран
class A : IDisposable
{
private bool _disposed;
~A()
{
this.Dispose(false);
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
// dispose managed resources
}
// clean up unmanaged resources
_disposed = true;
}
}
}
class Program
{
static void Main(string[] args)
{
using (var someInstance = new A())
{
// do some things with the class.
// once the using block completes, Dispose
// someInstance.Dispose() will automatically
// be called
}
}
}
Использование IDisposable
не может быть достаточно, потому что она опирается на пользователя запоминание вызвать Dispose
или использовать using
и т.д.
Для полного решения, объедините IDisposable
и финализатор. Как это:
Edit: Сделаны некоторые корректировки в методе Dispose на основе SpeksETC комментарий «s.
class MyClass : IDisposable
{
~MyClass()
{
Dispose(false);
}
public void Dispose()
{
GC.SupressFinalize();
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
if (!disposing)
{
// clear unmanaged resources here (can only be called once)
...
}
// dispose called explicitly by the user, clean up managed resources here
...
}
}
Это гарантирует, что местные ресурсы всегда будут очищены, даже если пользователь забывает позвонить Dispose
, в то же время позволяя пользователю очистить ресурсы рано.
if
внутри Dispose
реализация необходима, потому что, если этот класс находится на стадии завершения, вы не можете назвать Dispose
на своих членов, потому что они, возможно, были GC'ed уже.
+1: Хорошая работа, связанная с финализатором. По какой-то причине я подумал, что Microsoft начала обескураживать практику. – 2010-12-06 08:44:55
Финализаторы действительно имеют штраф за производительность, но я думаю, что это применимо только в том случае, если на самом деле вызывается финализатор (из-за накладных расходов GC, управляющих окончательной очередью и т. Д.). Таким образом, в вашем собственном приложении вы всегда должны утилизировать объекты, если сможете. Однако при написании библиотеки вы можете защитить своих пользователей, которые могут игнорировать вызов Dispose. Для них удар производительности будет лучше, чем утечка памяти ... – Ran 2010-12-06 08:58:22
Я думаю, что это очень важно отметить, что B является удалось ресурс, который только содержит неуправляемых ресурсов.
Поэтому A должен реализовывать IDisposable и удалять B в своем методе Dispose(), но не нуждается в финализаторе, так как у него нет неуправляемых ресурсов для очистки - финализатор должен быть реализован внутри самого B. Даже если вы реализовали финализации было бы назвать Dispose, который выглядел так:
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// dispose called explicitly by the user, clean up managed resources here
b.Dispose()
}
// no unmanaged resources to clean up so do nothing which makes Finalizer unneccesary
...
}
SpeksEtc является правильным в том, что если B содержит неуправляемые ресурсы, то B должен гарантировать, что нет никаких утечек не A.
Но что являются неуправляемыми ресурсами и поможет ли класс SafeHandle? Тогда B будет содержать SafeHandle, который будет содержать неуправляемый ресурс, и вам не нужно будет беспокоиться об этом.
Я не думаю, что Финализатор необходим в ситуации ОП. См. Мой ответ для получения дополнительной информации .... – SpeksETC 2010-12-06 10:37:49