JR>Я конечно за то, чтобы закрывать такие ресурсы сразу, но и без этого утечки хёндлов в DotNet не будет. Признаться, наблюдаемое поведение совпадает с моими представлениями, но может быть мои представления ошибочны? Как мне увидеть то явление, о котором вы говорили — то есть наблюдаемую в диспетчере ктечку от незакрытых явно стримов?
Мы обсуждаем утечку от незакрытых стримов или утечку вообще? Не приведу я вам примера. Это ж сколько надо хэндлов держать, чтобы цифра в диспетчере заметно увеличилась? Конечно, это не показатель. Но вообще, программы обычно делают не одну единственную глупость, а много разных вещей. Лучше сразу научиться хэндлы закрывать, чем потом когда-нибудь искать источник неприятностей.
Про раздраженный тон — боюсь это ваши собственые эмоции при чтении так преломляются.
Не хочу я никаких примеров приводить. Попробуйте устроиться на саппорт в контору, которая софт для разработчиков продает
Уж вам юзеры таких примеров покажут, никакой фантазии не хватит, чтобы это заранее вообразить. И даже в вашем описании теста, ооочень много ваших потенциальных клиентов нашли бы повод для скандала.
Ну давайте теперь про SafeHandle уточним. Когда будут хэндлы закрыты — при выходе из программы? Есть какая-то вероятность, что вот мы так все бросим, хэндлы сами собой через полчасика закроются, а программа будет продолжать работать?
Здравствуйте, notacat, Вы писали:
N>Мы обсуждаем утечку от незакрытых стримов или утечку вообще?
Ну лично я готов обсуждать с Вами что угодно и сколько угодно
Но вообще-то вроде Вы предлагали открывать в цикле стримы и это должно показать утечку памяти в диспетчере, что, в принципе, соответствует коду ТС. Но я не настаиваю, см. выше
N>Не приведу я вам примера.
Ну и ладно.
N>Это ж сколько надо хэндлов держать, чтобы цифра в диспетчере заметно увеличилась?
Да вобщем-то достаточно одного
Диспетчер, он их поштучно считает.
N>Конечно, это не показатель.
А что тогда показатель?
N>Но вообще, программы обычно делают не одну единственную глупость, а много разных вещей. Лучше сразу научиться хэндлы закрывать, чем потом когда-нибудь искать источник неприятностей.
Совершенно с Вами согласен. Но на утечки памяти процесса это не влияет. Точнее, на ту память которую мы тут как-бы пытались обсуждать... но молчу, молчу, во внутренности системы не лезу
N>Про раздраженный тон — боюсь это ваши собственые эмоции при чтении так преломляются.
Вот и чудненько, так и зафиксируем для истории
N>Не хочу я никаких примеров приводить. Попробуйте устроиться на саппорт в контору, которая софт для разработчиков продает Уж вам юзеры таких примеров покажут, никакой фантазии не хватит, чтобы это заранее вообразить. И даже в вашем описании теста, ооочень много ваших потенциальных клиентов нашли бы повод для скандала.
Да я уже понял
Бог с ним, с примером.
N>Ну давайте теперь про SafeHandle уточним.
Да-а-а-вайте
Только чур, не обвинять меня опять, что я утаскиваю обсуждение в дебри ОС, я совсем чуть-чуть, а Вы сами первая начали
N>Когда будут хэндлы закрыты — при выходе из программы? Есть какая-то вероятность, что вот мы так все бросим, хэндлы сами собой через полчасика закроются, а программа будет продолжать работать?
Хёндлы файлов, как и многих других объектов, закрываются фунцией CloseHandle. Сам по себе хёндл это целое число, размером IntPtr. В DotNet этот хёндл заворачивается в потомка SafeHandle, который в своём методе Dispose и вызывает CloseHandle. Кроме того, у него есть унаследованный от CriticalFinalizerObject виртуальный деструктор, в котором он вызывает свой-же виртуальный Dispose. Ну а когда вызывается деструктор объекта, Вы наверняка знаете не хуже, а то и лучше меня. Так что при одной из сборок мусора хёндлы будут закрыты сборщиком, а связанные с объектами буферы, как и сами объекты будут собраны ещё раньше. Причем чем чаще будет происходить сборка, тем быстрее они будут закрыты. Но и это можно ускорить. Я например, добавил к примеру вызов двух функций
GC.Collect();
GC.WaitForPendingFinalizers();
после чего показания диспетчера вообще практически "замёрзли".
Так что вероятность тут практически 100%
Но как Вы справедливо заметили, делать так не следует, прежде всего из-за недетерменированности момента закрытия хёндла, и всё это время объект, чей хёндл не закрыт, будет занят (не всегда, но — не углубляюсь
), а это может создать проблемы как для самого приложения, так и для сторонних процессов.
Ну и маленько для ТС. Пусть возьмёт эту функцию:
[DllImport("Kernel32.dll")]
static extern bool SetProcessWorkingSetSize(
IntPtr hProcess,
IntPtr dwMinimumWorkingSetSize,
IntPtr dwMaximumWorkingSetSize);
вызывает её вот так
var d = new IntPtr(-1);
SetProcessWorkingSetSize(d, d, d);
И радуется маленькому размеру занимаемой "памяти". Только когда его будут бить, то пусть не обижается и не говорит, что его не предупреждали.