Здравствуйте, takTak, Вы писали:
T>речь ж не о скорости, а о том, что программа принципиально работает различно в зависисмости лишь от небольшой разницы в размере данных: 85к и меньше — не работает, 85к и больше(это даже не один мегабайт, карл!) — работает
На стеке тоже точное количество свободного места: буфер байтом меньше ― всё работает, байтом больше ― всё вылетает к чертям. Ошибка в индексе массива всего на единицу вызывает IndexOutOfRangeException. Замена +1 на -1 может перевернуть изображение в окне вверх ногами и т.д. Наверняка можно придумать такой специальный сценарий, где OutOfMemory будет вылетать или не вылетать в зависимости от длины имени какой-нибудь переменной в коде.
Re[12]: WPF. Финализаторы не вызываются. Утечка памяти
T>>речь ж не о скорости, а о том, что программа принципиально работает различно в зависисмости лишь от небольшой разницы в размере данных: 85к и меньше — не работает, 85к и больше(это даже не один мегабайт, карл!) — работает
A>На стеке тоже точное количество свободного места: буфер байтом меньше ― всё работает, байтом больше ― всё вылетает к чертям. Ошибка в индексе массива всего на единицу вызывает IndexOutOfRangeException. Замена +1 на -1 может перевернуть изображение в окне вверх ногами и т.д. Наверняка можно придумать такой специальный сценарий, где OutOfMemory будет вылетать или не вылетать в зависимости от длины имени какой-нибудь переменной в коде.
это было бы справедливо, если бы в .NET не было так называемого автоматического управления памяти, но оно якобы есть!
Re[13]: WPF. Финализаторы не вызываются. Утечка памяти
Здравствуйте, takTak, Вы писали:
T>это было бы справедливо, если бы в .NET не было так называемого автоматического управления памяти, но оно якобы есть!
Управление есть, но сделать неправильно и всё сломать можно всегда, и это предусмотрено: кто-то же добавил OutOfMemoryException в список исключений Это при том, что суть сборщика мусора ― имитировать на устройстве бесконечное количество памяти.
НС>Для неуправляемых ресурсов и умеющих ими правильно пользоваться.
Почему недостаточно очистки неуправляемых ресурсов в методе IDisposable.Dispose() ?
Отвечайте на это сообщение, только если у Вас хорошее настроение и в Вашем ответе планируются только конструктивные вопросы и замечания http://rsdn.ru/Info/rules.xml
Re[14]: WPF. Финализаторы не вызываются. Утечка памяти
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Здравствуйте, igor-booch, Вы писали:
IB>>Почему недостаточно очистки неуправляемых ресурсов в методе IDisposable.Dispose() ?
НС>Потому что можно забыть позвать Dispose
Похоже на архитектурный кастыль, причем плохой, учитывая что
1) можно добавить неудачный финализатор и получить утечку памяти или OutOfMemoryException
2) финализатор может вызваться неизвестно когда
или вообще не вызваться (в этом случае получаем дополнительно п. 1)
3) финализаторы снижают производительность
Лучше при тестировании огребсти проблем с не вызванным Dispose, чем на продакшене получать плавающие ошибки.
Если финализаторы работают так плохо, я бы вообще их убрал из языка и тем более из паттерна Dispose
Отвечайте на это сообщение, только если у Вас хорошее настроение и в Вашем ответе планируются только конструктивные вопросы и замечания http://rsdn.ru/Info/rules.xml
Re[3]: WPF. Финализаторы не вызываются. Утечка памяти
С>>Мне кажется, что в оригинальном вопросе у вас в финализаторе освобождалось что-то другое. Зачем вам финализатор, если у вас нет неуправляемых ресурсов?
A>Не касаясь оригинальной задачи, пример использования финализаторов без неуправляемых ресурсов — контролировать утечки из пула.
У меня отписка слабого хендлера от события, как советуют здесь (Решение 3: Отписка от события в финализаторе)
Отвечайте на это сообщение, только если у Вас хорошее настроение и в Вашем ответе планируются только конструктивные вопросы и замечания http://rsdn.ru/Info/rules.xml
Здравствуйте, igor-booch, Вы писали:
IB>Это модельное (не реальное приложение). Я его создал, что хоть как-то продемонстрировать проблему. В реальной приложении финализатор не пустой и нет бесконечных циклов в конструкторе, но утечка памяти такая же.
IB>Лучше при тестировании огребсти проблем с не вызванным Dispose, чем на продакшене получать плавающие ошибки. IB>Если финализаторы работают так плохо, я бы вообще их убрал из языка и тем более из паттерна Dispose
Финализатор с отпиской слабого хендлера от события как советуют здесь (Решение 3: Отписка от события в финализаторе)
Отвечайте на это сообщение, только если у Вас хорошее настроение и в Вашем ответе планируются только конструктивные вопросы и замечания http://rsdn.ru/Info/rules.xml
S>Но не всегда можно вызвать Dispose, а освободить ресурсы необходимо.
Приведите пример, когда нельзя вызвать Dispose
Отвечайте на это сообщение, только если у Вас хорошее настроение и в Вашем ответе планируются только конструктивные вопросы и замечания http://rsdn.ru/Info/rules.xml
Re[18]: WPF. Финализаторы не вызываются. Утечка памяти
public abstract class SafeHandle : System.Runtime.ConstrainedExecution.CriticalFinalizerObject, IDisposable
{
...
~SafeHandle ();
}
class Unmanaged
{
public static SafeHandle OpenResource(string resourceName);
}
class ResourceHolder : IDisposable
{
SafeHandle _rsrcHandle;
public ResourceHolder()
{
_rsrcHandle = Unmanaged.OpenResource();//вызов какого-то метода, который может бросить exceptionthrow new SomeException();
}
public void Dispose()
{
_rsrcHandle.Dispose();
}
}
...
using (var r = new ResourceHolder())
{
}
//Dispose вызван не будет, но остается надежда на вызов Finalize (~SafeHandle).
Могло бы решиться обкладыванием где нужно try/catch и там вызывать Dispose, но так не делают, код превратится в кашу.
Re[18]: WPF. Финализаторы не вызываются. Утечка памяти
S>>Но не всегда можно вызвать Dispose, а освободить ресурсы необходимо. IB>Приведите пример, когда нельзя вызвать Dispose
Ну например возвращаешь в функции диспозабле объект, а тот кто получает и не знает, что он Dispose и проверку не производит, а может и не нужно вызывать Dispose и передавать еще дальше
Ты этим не управляешь.
А создатель объекта и не знает когда перестанут им пользоваться
и солнце б утром не вставало, когда бы не было меня
Re[13]: WPF. Финализаторы не вызываются. Утечка памяти
Здравствуйте, takTak, Вы писали:
T>это было бы справедливо, если бы в .NET не было так называемого автоматического управления памяти, но оно якобы есть!
Автоматическое управление памятью — это именно оно и есть, автоматическое управление памятью. Оно автоматически управляет памятью, а не чудеса творит. Как в бачке унитаза автоматическое управление уровнем воды. Оно вообще-то работает, но если поставить унитаз бачком под Ниагарский водопад, то бачок переполнится, несмотря на исправное и работающее автоматическое управление.
Re[16]: WPF. Финализаторы не вызываются. Утечка памяти
Здравствуйте, igor-booch, Вы писали:
IB>Похоже на архитектурный кастыль,
В мире нет почти ничего идеального.
IB>1) можно добавить неудачный финализатор и получить утечку памяти или OutOfMemoryException
Поэтому не надо использовать финализаторы, если не очень хорошо знаешь как они работают. Используй SafeHandle сотоварищи и не надо будет самому никаких финализаторов писать.
IB>2) финализатор может вызваться неизвестно когда IB>или вообще не вызваться (в этом случае получаем дополнительно п. 1) IB>3) финализаторы снижают производительность
Это прямое следствие использования асинхронного GC. Лучше пока никто не придумал.
IB>Если финализаторы работают так плохо,
Они нормально работают если правильно их использовать.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[19]: WPF. Финализаторы не вызываются. Утечка памяти
_>Могло бы решиться обкладыванием где нужно try/catch и там вызывать Dispose, но так не делают, код превратится в кашу.
Где здесь каша:
class Unmanaged
{
public static SafeHandle OpenResource(string resourceName);
}
class ResourceHolder : IDisposable
{
SafeHandle _rsrcHandle;
public ResourceHolder()
{
bool initialized = false;
try
{
_rsrcHandle = Unmanaged.OpenResource();
//вызов какого-то метода, который может бросить exception
initialized = true;
}
finally
{
if (!initialized)
_rsrcHandle.Dispose();
}
}
public void Dispose()
{
_rsrcHandle.Dispose();
}
}
...
using (var r = new ResourceHolder())
{
}
А здесь?:
class Unmanaged
{
public static SafeHandle OpenResource(string resourceName);
}
class ResourceHolder : IDisposable
{
SafeHandle _rsrcHandle;
public ResourceHolder()
{
}
public Initialize()
{
_rsrcHandle = Unmanaged.OpenResource();
}
public void Dispose()
{
_rsrcHandle.Dispose();
}
}
...
using (var r = new ResourceHolder())
{
r.Initialize();
}
Отвечайте на это сообщение, только если у Вас хорошее настроение и в Вашем ответе планируются только конструктивные вопросы и замечания http://rsdn.ru/Info/rules.xml
Re[20]: WPF. Финализаторы не вызываются. Утечка памяти
Здравствуйте, igor-booch, Вы писали:
_>>Могло бы решиться обкладыванием где нужно try/catch и там вызывать Dispose, но так не делают, код превратится в кашу.
IB>Где здесь каша:
Добавь еще 5-10 таких полей, и будет каша.
Я же не сказал что это невозможно, я указал что так не делают, обычно, и типичный код — такой какой я привел
В частных случаях да, когда железно прям щас нужно освободить ресурс — да, так имеет смысл делать.
ps: ты же сам выбрал "ленивый" способ отписки от событий в Finalize , чем Dispose не устроил?
Re[21]: WPF. Финализаторы не вызываются. Утечка памяти
Здравствуйте, pilgrim_, Вы писали:
_>Здравствуйте, igor-booch, Вы писали:
_>>>Могло бы решиться обкладыванием где нужно try/catch и там вызывать Dispose, но так не делают, код превратится в кашу.
IB>>Где здесь каша:
_>Добавь еще 5-10 таких полей, и будет каша.
Просто интересно как получается каша
class Unmanaged
{
public static SafeHandle OpenResource(string resourceName);
}
class ResourceHolder : IDisposable
{
SafeHandle _rsrcHandle;
SafeHandle _rsrcHandle1;
SafeHandle _rsrcHandle2;
SafeHandle _rsrcHandle3;
SafeHandle _rsrcHandle4;
SafeHandle _rsrcHandle5;
public ResourceHolder()
{
bool initialized = false;
try
{
_rsrcHandle = Unmanaged.OpenResource();
_rsrcHandle1 = Unmanaged.OpenResource();
_rsrcHandle2 = Unmanaged.OpenResource();
_rsrcHandle3 = Unmanaged.OpenResource();
_rsrcHandle4 = Unmanaged.OpenResource();
_rsrcHandle5 = Unmanaged.OpenResource();
//вызов какого-то метода, который может бросить exception
initialized = true;
}
finally
{
if (!initialized)
Dispose();
}
}
public void Dispose()
{
_rsrcHandle?.Dispose();
_rsrcHandle1?.Dispose();
_rsrcHandle2?.Dispose();
_rsrcHandle3?.Dispose();
_rsrcHandle4?.Dispose();
_rsrcHandle5?.Dispose();
}
}
...
using (var r = new ResourceHolder())
{
}
Отвечайте на это сообщение, только если у Вас хорошее настроение и в Вашем ответе планируются только конструктивные вопросы и замечания http://rsdn.ru/Info/rules.xml
Re[21]: WPF. Финализаторы не вызываются. Утечка памяти
_>ps: ты же сам выбрал "ленивый" способ отписки от событий в Finalize , чем Dispose не устроил?
Потому-что усложняется API. Я за простоту.
Отвечайте на это сообщение, только если у Вас хорошее настроение и в Вашем ответе планируются только конструктивные вопросы и замечания http://rsdn.ru/Info/rules.xml
Re[3]: WPF. Финализаторы не вызываются. Утечка памяти
Здравствуйте, igor-booch, Вы писали:
IB>Финализатор с отпиской слабого хендлера от события как советуют здесь (Решение 3: Отписка от события в финализаторе)
Мой тебе совет — не стоит использовать хабр как источник технической информации.