Условия воспроизведения:
1) Visual Studio 2017
2) Приложение WPF
3) Запуск приложение под отладчиком
4) код окна WPF
using System.Windows;
namespace ReproduceFinalizerMemoryLeak
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
do
{
Item item = new Item();
} while (true);
InitializeComponent();
}
}
public class Item
{
private byte[] _bytes;
public Item()
{
_bytes = new byte[10000];
}
~Item()
{
}
}
}
Что присходит:
Этот код отваливается с OutOfMemoryException. Финализаторы Item() не вызываются.
В моем реальном WPF приложении утечка памяти просходит без отладки и в более мягких условиях, но проявления те же: финализаторы не вызываются, происходит учечка памяти.
Отвечайте на это сообщение, только если у Вас хорошее настроение и в Вашем ответе планируются только конструктивные вопросы и замечания http://rsdn.ru/Info/rules.xml
Re: WPF. Финализаторы не вызываются. Утечка памяти
IB>Что присходит: IB>Этот код отваливается с OutOfMemoryException. Финализаторы Item() не вызываются.
IB>В моем реальном WPF приложении утечка памяти просходит без отладки и в более мягких условиях, но проявления те же: финализаторы не вызываются, происходит учечка памяти.
забавно: если деконструктор
~Item()
{
}
полностью убрать, то всё работает
Re: WPF. Финализаторы не вызываются. Утечка памяти
IB>using System.Windows;
IB>namespace ReproduceFinalizerMemoryLeak
IB>{
IB> /// <summary>
IB> /// Interaction logic for MainWindow.xaml
IB> /// </summary>
IB> public partial class MainWindow : Window
IB> {
IB> public MainWindow()
IB> {
IB> do
IB> {
IB> TheMethod();
IB> } while (true);
IB> InitializeComponent();
IB> }
TheMethod() { Item item = new Item(); }
IB> }
IB> public class Item
IB> {
IB> private byte[] _bytes;
IB> public Item()
IB> {
IB> _bytes = new byte[10000];
IB> }
IB> ~Item()
IB> {
IB> }
IB> }
IB>}
IB>
IB>Что присходит: IB>Этот код отваливается с OutOfMemoryException. Финализаторы Item() не вызываются.
IB>В моем реальном WPF приложении утечка памяти просходит без отладки и в более мягких условиях, но проявления те же: финализаторы не вызываются, происходит учечка памяти.
Re[2]: WPF. Финализаторы не вызываются. Утечка памяти
T>>забавно: если деконструктор T>>полностью убрать, то всё работает
НС>Чего ж тут забавного? Объекты перестает держать fqueue и GC прекрасно справляется со сборкой.
вообще-то GC сам должен заглядывать во fqueue и всё там подчищать,
и если использовать больший массив _bytes = new byte[100000], то всё, как ожидается и работает,
если же взять _bytes = new byte[10000], то происходит outOfMemory
Re[4]: WPF. Финализаторы не вызываются. Утечка памяти
Здравствуйте, takTak, Вы писали:
T>вообще-то GC сам должен заглядывать во fqueue и всё там подчищать,
Он не может там подчистить без вызова финализаторов, а это потенциально долго.
T>и если использовать больший массив _bytes = new byte[100000], то всё, как ожидается и работает,
100К попадает в LOH, там несколько другие алгоритмы.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[2]: WPF. Финализаторы не вызываются. Утечка памяти
T>>вообще-то GC сам должен заглядывать во fqueue и всё там подчищать,
НС>Он не может там подчистить без вызова финализаторов, а это потенциально долго.
если бы в Item не было вы массива, то всё бы тоже работало, даже с наследованием,
проблема в сочетании деконструктора и небольшого массива внутри объекта
T>>и если использовать больший массив _bytes = new byte[100000], то всё, как ожидается и работает,
НС>100К попадает в LOH, там несколько другие алгоритмы.
да, согласен, там другой алгоритм, и он справляется
Re[6]: WPF. Финализаторы не вызываются. Утечка памяти
T>>>вообще-то GC сам должен заглядывать во fqueue и всё там подчищать,
НС>>Он не может там подчистить без вызова финализаторов, а это потенциально долго.
T>если бы в Item не было вы массива, то всё бы тоже работало, даже с наследованием, T>проблема в сочетании деконструктора и небольшого массива внутри объекта
не, даже без вложенного массива комбинация деконструктора и бесконечного цикла ведёт к outofmemory,
хотя в finalizer программа регулярно заходит
Re[3]: WPF. Финализаторы не вызываются. Утечка памяти
Здравствуйте, takTak, Вы писали: T>единственное, что всё меняет: это наличие или отсутствие деконструктора
Деконструктор в дотнет — это метод Deconstruct. Он применяется для паттерн-матчинга и для деконструирующих присваиваний.
А то, о чём вы говорите, называется финализатором.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[4]: WPF. Финализаторы не вызываются. Утечка памяти
T>>единственное, что всё меняет: это наличие или отсутствие деконструктора S>Деконструктор в дотнет — это метод Deconstruct. Он применяется для паттерн-матчинга и для деконструирующих присваиваний. S>А то, о чём вы говорите, называется финализатором.
забавно: в русском языке есть заимствовование "конструктор", так вот антонимом ему является не "деконструктор", а "деструктор",
"финализатор" на https://ru.wiktionary.org/ не находится
Re[5]: WPF. Финализаторы не вызываются. Утечка памяти
Здравствуйте, takTak, Вы писали: T>забавно: в русском языке есть заимствовование "конструктор", так вот антонимом ему является не "деконструктор", а "деструктор", T>"финализатор" на https://ru.wiktionary.org/ не находится
Мы говорим не о литературном русском языке, а о терминологии производителя. Деструкторов в CLR нет, т.к. деструктор подразумевает детерминистическую финализацию.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[6]: WPF. Финализаторы не вызываются. Утечка памяти
T>>забавно: в русском языке есть заимствовование "конструктор", так вот антонимом ему является не "деконструктор", а "деструктор", T>>"финализатор" на https://ru.wiktionary.org/ не находится S>Мы говорим не о литературном русском языке, а о терминологии производителя. Деструкторов в CLR нет, т.к. деструктор подразумевает детерминистическую финализацию.
если обратно к нашим баранам, то
Use of finalize() methods should be avoided. They are not a reliable mechanism for resource clean up and it is possible to cause problems in the garbage collector by abusing them.
что мы, в принципе, на этом примере и видим
Re[6]: WPF. Финализаторы не вызываются. Утечка памяти
T>>проблема в сочетании деконструктора и небольшого массива внутри объекта
НС>Нет. Проблема в большом количестве финализаторов и быстром выжирании пулов поколений.
ну да, похоже на такое...
как вообще происходит "быстрое выжирание пулов поколений" и почему gc.collect этому "выжиранию" препятствует?
Re[8]: WPF. Финализаторы не вызываются. Утечка памяти
T>>как вообще происходит "быстрое выжирание пулов поколений"
НС>Путем быстрого выделения большого количества объектов.
T>>и почему gc.collect этому "выжиранию" препятствует?
НС>Потому что останавливает выделение и дает отработать финалайзерам.
для меня лично такое- это откровенный баг: если автоматическое управление памятью с выделением памяти под большие обьекты справляется, а с выделением паняти под маленькие объекты не справляется, то это — полная ерунда ...
Re[8]: WPF. Финализаторы не вызываются. Утечка памяти
Здравствуйте, takTak, Вы писали:
T>>>проблема в сочетании деконструктора и небольшого массива внутри объекта
НС>>Нет. Проблема в большом количестве финализаторов и быстром выжирании пулов поколений.
T>ну да, похоже на такое...
T>как вообще происходит "быстрое выжирание пулов поколений" и почему gc.collect этому "выжиранию" препятствует?
gc.collect как раз и переводит из поколения в поколение. Со старшими поколениями видно и происходит проблема с финализаторами.
Там считается если уж попал во 2 е поколение то это на долго.
А GC.WaitForPendingFinalizers(); принудительно дожидается пока все финализаторы не сработают
и солнце б утром не вставало, когда бы не было меня
Re[10]: WPF. Финализаторы не вызываются. Утечка памяти
Здравствуйте, takTak, Вы писали:
T>для меня лично такое- это откровенный баг
Для тебя лично. Этому поведению уже 20 лет скоро.
T>: если автоматическое управление памятью с выделением памяти под большие обьекты справляется, а с выделением паняти под маленькие объекты не справляется, то это — полная ерунда ...
Полная ерунда это писать финалайзеры не соображая как это работает. Сама идея делать финалайзеры без неуправляемых ресурсов уже бред.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[11]: WPF. Финализаторы не вызываются. Утечка памяти
T>>для меня лично такое- это откровенный баг
НС>Для тебя лично. Этому поведению уже 20 лет скоро.
T>>: если автоматическое управление памятью с выделением памяти под большие обьекты справляется, а с выделением паняти под маленькие объекты не справляется, то это — полная ерунда ...
НС>Полная ерунда это писать финалайзеры не соображая как это работает. Сама идея делать финалайзеры без неуправляемых ресурсов уже бред.
так я лично поэтому всегда Dispose и пользовался, краем уха слышал, что пользоваться finalizer не стоит...
так нафига finalizer воообще, если это банально не работает ?
Re[12]: WPF. Финализаторы не вызываются. Утечка памяти
Здравствуйте, takTak, Вы писали:
НС>>Полная ерунда это писать финалайзеры не соображая как это работает. Сама идея делать финалайзеры без неуправляемых ресурсов уже бред.
T>так я лично поэтому всегда Dispose и пользовался, краем уха слышал, что пользоваться finalizer не стоит...
T>так нафига finalizer воообще, если это банально не работает ?
Здравствуйте, takTak, Вы писали:
S>>Мы говорим не о литературном русском языке, а о терминологии производителя. Деструкторов в CLR нет, т.к. деструктор подразумевает детерминистическую финализацию.
T>другие люди почему-то используют...
И они не правы, потому что слово "finalizer" для того и придумали, чтобы избежать слова "destructor".
Re: WPF. Финализаторы не вызываются. Утечка памяти
Мне кажется, что в оригинальном вопросе у вас в финализаторе освобождалось что-то другое. Зачем вам финализатор, если у вас нет неуправляемых ресурсов?
Re[8]: WPF. Финализаторы не вызываются. Утечка памяти
S>>>Мы говорим не о литературном русском языке, а о терминологии производителя. Деструкторов в CLR нет, т.к. деструктор подразумевает детерминистическую финализацию.
T>>другие люди почему-то используют...
bnk>И они не правы, потому что слово "finalizer" для того и придумали, чтобы избежать слова "destructor".
имхо никакого смысла плодить ненужные сущности нет: могли назвать недерминистическим дестрактором, тогда всем было бы всё понятно,
а чего стоит их "selectMany" в linq !? Поубибав бы(c)
Re[8]: WPF. Финализаторы не вызываются. Утечка памяти
Здравствуйте, bnk, Вы писали:
bnk>И они не правы, потому что слово "finalizer" для того и придумали, чтобы избежать слова "destructor".
Ага, слово то дали другое, а синтаксис в C# скопирован с деструкторов.
Лучше бы как в Java пиши полностью: public override void Finalize(), тогда бы и меньше людей пихало бы в код финализаторов.
Здравствуйте, _NN_, Вы писали:
bnk>>И они не правы, потому что слово "finalizer" для того и придумали, чтобы избежать слова "destructor".
_NN>Ага, слово то дали другое, а синтаксис в C# скопирован с деструкторов. _NN>Лучше бы как в Java пиши полностью: public override void Finalize(), тогда бы и меньше людей пихало бы в код финализаторов.
Компромисс? Людям нужны знакомые вещи, пусть они немного и не такие какими кажутся
bnk>>>И они не правы, потому что слово "finalizer" для того и придумали, чтобы избежать слова "destructor".
_NN>>Ага, слово то дали другое, а синтаксис в C# скопирован с деструкторов. _NN>>Лучше бы как в Java пиши полностью: public override void Finalize(), тогда бы и меньше людей пихало бы в код финализаторов.
bnk>Компромисс? Людям нужны знакомые вещи, пусть они немного и не такие какими кажутся
ага, если что-то выглядит как утка, но то мяукуает, то хрюкает, то как это назвать ?
Re[2]: WPF. Финализаторы не вызываются. Утечка памяти
IB>>Создал минимальное воспроизводящее приложение.
С>Мне кажется, что в оригинальном вопросе у вас в финализаторе освобождалось что-то другое. Зачем вам финализатор, если у вас нет неуправляемых ресурсов?
Это модельное (не реальное приложение). Я его создал, что хоть как-то продемонстрировать проблему. В реальной приложении финализатор не пустой и нет бесконечных циклов в конструкторе, но утечка памяти такая же.
Отвечайте на это сообщение, только если у Вас хорошее настроение и в Вашем ответе планируются только конструктивные вопросы и замечания http://rsdn.ru/Info/rules.xml
Re[6]: WPF. Финализаторы не вызываются. Утечка памяти
Здравствуйте, Sinclair, Вы писали:
S>Мы говорим не о литературном русском языке, а о терминологии производителя. Деструкторов в CLR нет, т.к. деструктор подразумевает детерминистическую финализацию.
Ага. Повбивав би
Дать название из C++, а поведение совсем не такое как у деструкторов из C++:
Execution of the destructor for the instance may occur at any time after the instance becomes eligible for destruction.
When an instance is destructed, the destructors in that instance's inheritance chain are called, in order, from most derived to least derived.
A destructor may be executed on any thread.
Здравствуйте, Слава, Вы писали:
С>Мне кажется, что в оригинальном вопросе у вас в финализаторе освобождалось что-то другое. Зачем вам финализатор, если у вас нет неуправляемых ресурсов?
Не касаясь оригинальной задачи, пример использования финализаторов без неуправляемых ресурсов — контролировать утечки из пула.
Есть пул объектов (или их дорого инициализировать, или они большие и хочется переиспользовать память в LOH). Если при выдаче из пула подписывать объект на финализацию, а при возвращении в пул отписывать, а в финализатор вставить логирование, то вызов GC.Collect+WaitForPendingFinalizers покажет, а не утекло ли у нас что-то мимо пула.
Re[7]: WPF. Финализаторы не вызываются. Утечка памяти
Здравствуйте, takTak, Вы писали:
T>не, даже без вложенного массива комбинация деконструктора и бесконечного цикла ведёт к outofmemory, T>хотя в finalizer программа регулярно заходит
Объекты создаются в цикле быстрее, чем поток финализации успевает обрабатывать их финализаторы, а GC не может убивать старые объекты, пока их финализаторы не отработали.
Re[8]: WPF. Финализаторы не вызываются. Утечка памяти
T>>не, даже без вложенного массива комбинация деконструктора и бесконечного цикла ведёт к outofmemory, T>>хотя в finalizer программа регулярно заходит
A>Объекты создаются в цикле быстрее, чем поток финализации успевает обрабатывать их финализаторы, а GC не может убивать старые объекты, пока их финализаторы не отработали.
так проблема для меня лично не столько в этом, а в том, что деструкторы больших по размеру объектов при всём этом без проблем работают : получается противоречивое поведение, когда программа ведёт себя различно в зависимости лишь от разницы в размере данных
Re[9]: WPF. Финализаторы не вызываются. Утечка памяти
Здравствуйте, takTak, Вы писали:
A>>Объекты создаются в цикле быстрее, чем поток финализации успевает обрабатывать их финализаторы, а GC не может убивать старые объекты, пока их финализаторы не отработали. T>так проблема для меня лично не столько в этом, а в том, что деструкторы больших по размеру объектов при всём этом без проблем работают
Повод измерить и сравнить скорость выделения 10кб в нулевом поколении и 100кб в large object heap. Если во втором случае заметно дольше, то финализаторы успевают отрабатывать.
T>>> получается противоречивое поведение, когда программа ведёт себя различно в зависимости лишь от разницы в размере данных
Это очевидная зависимость. Выдели на стеке буфер в мегабайт, а потом в десять мегабайт. Во втором случае будет StackOverflow. Ну, сам виноват, не уследил за размерами. И конечно большие объёмы данных обрабатывать дольше, чем маленькие ― скорость работы программы не может не отличаться.
A>>>Объекты создаются в цикле быстрее, чем поток финализации успевает обрабатывать их финализаторы, а GC не может убивать старые объекты, пока их финализаторы не отработали. T>>так проблема для меня лично не столько в этом, а в том, что деструкторы больших по размеру объектов при всём этом без проблем работают
A>Повод измерить и сравнить скорость выделения 10кб в нулевом поколении и 100кб в large object heap. Если во втором случае заметно дольше, то финализаторы успевают отрабатывать.
T>>>> получается противоречивое поведение, когда программа ведёт себя различно в зависимости лишь от разницы в размере данных
A>Это очевидная зависимость. Выдели на стеке буфер в мегабайт, а потом в десять мегабайт. Во втором случае будет StackOverflow. Ну, сам виноват, не уследил за размерами. И конечно большие объёмы данных обрабатывать дольше, чем маленькие ― скорость работы программы не может не отличаться.
речь ж не о скорости, а о том, что программа принципиально работает различно в зависисмости лишь от небольшой разницы в размере данных: 85к и меньше — не работает, 85к и больше(это даже не один мегабайт, карл!) — работает
Re[11]: WPF. Финализаторы не вызываются. Утечка памяти
Здравствуйте, 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: Отписка от события в финализаторе)
Мой тебе совет — не стоит использовать хабр как источник технической информации.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[4]: WPF. Финализаторы не вызываются. Утечка памяти
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Здравствуйте, igor-booch, Вы писали:
IB>>Финализатор с отпиской слабого хендлера от события как советуют здесь (Решение 3: Отписка от события в финализаторе)
НС>Мой тебе совет — не стоит использовать хабр как источник технической информации.
Здравствуйте, igor-booch, Вы писали:
S>>Но не всегда можно вызвать Dispose, а освободить ресурсы необходимо. IB>Приведите пример, когда нельзя вызвать Dispose
Эмм, ну вот например как-то так:
var myFile = File.OpenWrite("C:\temp\0asdask12.txt");
Thread.Create(o=>myFile.Write(Encoding.UTF-8.GetBytes(o.ToString())).Start(myBigObject);
Где вы тут будете звать Dispose()?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[19]: WPF. Финализаторы не вызываются. Утечка памяти
Отвечайте на это сообщение, только если у Вас хорошее настроение и в Вашем ответе планируются только конструктивные вопросы и замечания http://rsdn.ru/Info/rules.xml
Здравствуйте, igor-booch, Вы писали:
IB>Условия воспроизведения: IB>1) Visual Studio 2017 IB>2) Приложение WPF IB>3) Запуск приложение под отладчиком IB>4) код окна WPF
IB>Этот код отваливается с OutOfMemoryException. Финализаторы Item() не вызываются.
Зпустил под VS2019 все работает нормально, память не растет.
Re[20]: WPF. Финализаторы не вызываются. Утечка памяти
Открою тебе секрет зачем был придуман GС.
В С++ вручную овобождают память в куче (там есть и подсчет ссылок, и shared_ptr). Но не всегда это возможно. В COM применяли подсчет ссылок, но были циклические ссылки которые не разруливались.
Объектом могут владеть множество других объектов, и нужно освобождать ресурсы когда ссылок на них нет.
и солнце б утром не вставало, когда бы не было меня
Re[2]: WPF. Финализаторы не вызываются. Утечка памяти
Здравствуйте, HotDog, Вы писали:
HD>Здравствуйте, igor-booch, Вы писали:
IB>>Условия воспроизведения: IB>>1) Visual Studio 2017 IB>>2) Приложение WPF IB>>3) Запуск приложение под отладчиком IB>>4) код окна WPF
IB>>Этот код отваливается с OutOfMemoryException. Финализаторы Item() не вызываются.
HD>Зпустил под VS2019 все работает нормально, память не растет.
У меня в 2019 тоже раблтает
Отвечайте на это сообщение, только если у Вас хорошее настроение и в Вашем ответе планируются только конструктивные вопросы и замечания http://rsdn.ru/Info/rules.xml