Re[14]: Утечки памяти?
От: koandrew Канада http://thingselectronic.blogspot.ca/
Дата: 28.09.10 17:37
Оценка:
Здравствуйте, Jolly Roger, Вы писали:

JR>Да, С2 требует. Но если я правильно помню, прямой корелляции между освобождённой памятью и изменением рабочего набора я не заметил. То есть механизм, видимо, действует несколько сложнее. Впрочем, так как это было не вчера, то есть вероятность, что память меня таки подводит В любом случае, каждый желающий всегда может поставить экспиремент самостоятельно.


Вот тут написано про рабочий набор: http://msdn.microsoft.com/en-us/library/cc441804(v=VS.85).aspx Там же написано, когда он растёт, и когда уменьшается. В общем, как говорится, RTFM
[КУ] оккупировала армия.
Re[14]: Утечки памяти?
От: v.a.v СССР  
Дата: 28.09.10 17:41
Оценка:
Здравствуйте, Jolly Roger, Вы писали:

JR>Здравствуйте, koandrew, Вы писали:


K>>Это не так. Винда (по крайней мере серверная) сертифицирована по стандарту безопасности С2, который среди всего прочего требует, чтобы ядро ОС всегда обнуляло страницы перед передачей их приложению. Об этом кстати у Рихтера написано.


JR>Да, С2 требует. Но если я правильно помню, прямой корелляции между освобождённой памятью и изменением рабочего набора я не заметил. То есть механизм, видимо, действует несколько сложнее. Впрочем, так как это было не вчера, то есть вероятность, что память меня таки подводит В любом случае, каждый желающий всегда может поставить экспиремент самостоятельно.


C2 требует именно обнуления памяти перед выдачей ее процессу?
Может быть требуется просто не допускать возможности чтения процессом чужого "мусора" в свежеполученной памяти? Это ведь разные вещи. Возможность чтения процессом собственного "мусора" врядли повлияет на безопасность.
Re[2]: Утечки памяти?
От: Flammable Россия  
Дата: 28.09.10 18:43
Оценка:
Здравствуйте, debugx, Вы писали:

D>Код покажите.

D>Может вы там еще какие-нибудь хештаблицы создаете, которые подгружают кучу левых дллок в память

StreamReader myReader = null;
foreach (string FilePath in FilePathes)
{
MapIDReader = new StreamReader(FilePath, Encoding.GetEncoding(1251));
while (!MapIDReader.EndOfStream)
{
MapLine = MapIDReader.ReadLine();
if (MapLine.Contains(@"map\"))
{
MapLine = MapLine.Trim();
if (MapLine.StartsWith("texture"))
{
MapName = MapLine.Substring(MapLine.IndexOf(@"map\") + 8);
break;
}
}
}
MapNames[i] = MapName;
i++;
}
MapID.Close();
Re[2]: Утечки памяти?
От: Flammable Россия  
Дата: 28.09.10 18:48
Оценка:
Здравствуйте, debugx, Вы писали:

D>Код покажите.

D>Может вы там еще какие-нибудь хештаблицы создаете, которые подгружают кучу левых дллок в память

StreamReader MapIDReader = null;
foreach (string FilePath in FilePathes)
{
MapIDReader = new StreamReader(FilePath, Encoding.GetEncoding(1251));
while (!MapIDReader.EndOfStream)
{
MapLine = MapIDReader.ReadLine();
if (MapLine.Contains(@"map\"))
{
MapLine = MapLine.Trim();
if (MapLine.StartsWith("texture"))
{
MapName = MapLine.Substring(MapLine.IndexOf(@"map\") + 8);
break;
}
}
}
MapNames[i] = MapName;
i++;
}
MapID.Close();
Re[3]: Утечки памяти?
От: notacat  
Дата: 28.09.10 18:52
Оценка: +1
Почему-то я примерно так это себе и представляла.
Работающий код, пожалуйста. То, что вы написали, работать не может.

Ну даже если предположим, что myReader, MapIDReader и MapID — это одна и та же переменная, которая переименовалась при копипасте, то все равно надо ридеры закрывать внутри цикла, т.е. на каждый new StreamReader должен быть вызов StreamReader.Close().
А в вашем коде вы закрываете только один последний, а создаете их много — по одному для каждого файла.
Re[15]: Утечки памяти?
От: Jolly Roger  
Дата: 29.09.10 00:37
Оценка: +1
Здравствуйте, v.a.v, Вы писали:

VAV>C2 требует именно обнуления памяти перед выдачей ее процессу?

VAV>Может быть требуется просто не допускать возможности чтения процессом чужого "мусора" в свежеполученной памяти? Это ведь разные вещи. Возможность чтения процессом собственного "мусора" врядли повлияет на безопасность.

С2 требует обнуления, если страница передаётся другому процессу и если она была текущим процессом модифицирована. В этом случае она попадает к потоку обнуления страниц, а оттуда опять в ведение менеджера набора.
"Нормальные герои всегда идут в обход!"
Re[15]: Утечки памяти?
От: Jolly Roger  
Дата: 29.09.10 00:46
Оценка:
Здравствуйте, koandrew, Вы писали:

K>Вот тут написано про рабочий набор: http://msdn.microsoft.com/en-us/library/cc441804(v=VS.85).aspx Там же написано, когда он растёт, и когда уменьшается. В общем, как говорится, RTFM


Да это я читал, а что не так? Это описание слишком уж расплывчатое, явно видно цель — не сказать-бы чего лишнего Но и там, кстати сказано "Pages can be removed", а не, скажем "are removed", да и VirtualFree не упомянута, хорошо хоть про VirtualUnlock не забыли
"Нормальные герои всегда идут в обход!"
Re[4]: Утечки памяти?
От: Jolly Roger  
Дата: 29.09.10 02:05
Оценка:
Здравствуйте, notacat, Вы писали:

Закрывать конечно надо, всё правильно, только вряд-ли это повлияет на обсуждаемое. Не тот показатель ТС использует. Да и вообще, пытаться определить утечки с помощью дисперчера задач для приложений, имеющих локальный менеджер памяти — занятие, мягко говоря, странное. Это его работа, локального менеджер — брать у системы большие регионы памяти и потом выдавать приложению частями по мере надобности, для того локальные менеджеры и пишутся даже там, где GC нет. Ну и отдавать системе память сразу при её освобождении приложением было-бы неразумно с точки зрения производительности, ни один менеджер этого и не делает, а диспетчер задач видит именно то, что взял у системы локальный менеджер процесса. Тем более что это просто диапазон адресов, имеющий смысл только для локального процесса, и влияние его на другие процессы и систему в целом весьма ограничено. Впрочем, об этом уже говорилось.
"Нормальные герои всегда идут в обход!"
Re[4]: Утечки памяти?
От: Flammable Россия  
Дата: 29.09.10 04:10
Оценка:
Здравствуйте, notacat, Вы писали:

N>Почему-то я примерно так это себе и представляла.

N>Работающий код, пожалуйста. То, что вы написали, работать не может.

N>Ну даже если предположим, что myReader, MapIDReader и MapID — это одна и та же переменная, которая переименовалась при копипасте, то все равно надо ридеры закрывать внутри цикла, т.е. на каждый new StreamReader должен быть вызов StreamReader.Close().

N>А в вашем коде вы закрываете только один последний, а создаете их много — по одному для каждого файла.

Извиняйте, копипаст действительно кривой, не проверил.
Вот полный код метода:

private string[] GetSocMapNames(string RootFolder)
        {
            string[] Maps = Directory.GetFiles(RootFolder + @"\mods", "*.xdb0");
            string[] MapNames = new string[Maps.Length];
            string MapLine = "", MapName = "";
            StreamReader MapID = null;
            int i = 0;
            foreach (string map in Maps)
            {
                Application.DoEvents();
                MapID = new StreamReader(map, Encoding.GetEncoding(1251));
                while (!MapID.EndOfStream)
                {
                    MapLine = MapID.ReadLine();
                    if (MapLine.Contains(@"map\"))
                    {
                        MapLine = MapLine.Trim();
                        if (MapLine.StartsWith("texture"))
                        {
                            MapName = MapLine.Substring(MapLine.IndexOf(@"map\") + 8); ////
                            break;
                        }
                    }
                }
                MapNames[i] = MapName;
                i++;
            }
            MapID.Close();
            return MapNames;
        }
Re[5]: Утечки памяти?
От: Кондраций Россия  
Дата: 29.09.10 04:54
Оценка:
Здравствуйте, Flammable, Вы писали:


...
О чём и говорили. Закрывай стримы явно каждый либо (что лучше) просто используй using.
Сообщение заговорено потомственным колдуном, целителем и магом в девятом поколении!
Модерирование или минусование сообщения ведет к половому бессилию, венерическим заболеваниям, венцу безбрачия и диарее!
Re[5]: Утечки памяти?
От: Jesmus Россия  
Дата: 29.09.10 06:06
Оценка:
Здравствуйте, Flammable, Вы писали:

F>Вот полный код метода:



1) Повесить using на создание reader, убрать Close().
2) Этот код будет падать (NullReferenceException) если в каталоге нет ни одного файла с нужной маской (на MapID.Close()).
3) MapName не чистится в каждой итерации цикла — в итоге MapNames[] может оказаться заполнен мусорными значениями с прошлых итераций (в первом файле texture была, в остальных нет)
4) DoEvents действительно здесь нужна? Просто практика показывает что от этого метода проблема ой как много, а нужен он ой как редко.
Re[16]: Утечки памяти?
От: v.a.v СССР  
Дата: 29.09.10 07:30
Оценка:
Здравствуйте, Jolly Roger, Вы писали:

JR>Здравствуйте, v.a.v, Вы писали:


VAV>>C2 требует именно обнуления памяти перед выдачей ее процессу?

VAV>>Может быть требуется просто не допускать возможности чтения процессом чужого "мусора" в свежеполученной памяти? Это ведь разные вещи. Возможность чтения процессом собственного "мусора" врядли повлияет на безопасность.

JR>С2 требует обнуления, если страница передаётся другому процессу и если она была текущим процессом модифицирована. В этом случае она попадает к потоку обнуления страниц, а оттуда опять в ведение менеджера набора.


И я о том-же. Нет смысла обнулять страницу если планируется её вернуть тому-же процессу. Это не противоречит требованиям C2.
А учитывая что:
"Pages can be removed", а не, скажем "are removed"

Вы были правы, что станицы могут не удаляться из рабочего набора, сразу после их освобождения процессом.
Re[5]: Утечки памяти?
От: notacat  
Дата: 29.09.10 09:59
Оценка:
JR>Закрывать конечно надо, всё правильно, только вряд-ли это повлияет на обсуждаемое. Не тот показатель ТС использует. Да и вообще, пытаться определить утечки с помощью дисперчера задач для приложений, имеющих локальный менеджер памяти — занятие, мягко говоря, странное.
Поверьте на слово, что если упорно не закрывать стримы и не освобождать ссылки, то даже диспетчер задач это покажет. И если сделать пример, в котором подозрительные действия выполняются в цикле, и аккуратно просить каждый раз GC все лишнее почистить, то за несколько итераций в диспетчере задач прекрасно видно, течет память или не течет.
А вот остальные детали и лечение — это уже конечно не к диспетчеру задач надо обращаться.

Ну и отдельный вопрос — что половина участников уже забыла, что нужно было топик стартеру. Вы уже все внутренности Windows обсудили, но это не значит, что именно это является обсуждаемым.
Re[10]: Утечки памяти?
От: Аноним  
Дата: 29.09.10 10:35
Оценка: 21 (1) :))
Здравствуйте, Don Reba, Вы писали:

DR>Здравствуйте, Jolly Roger, Вы писали:


JR>>Если не хочется углубляться в механизмы, то можно принять за аксиому, что управление памятью в Windows писали отнюдь не ламеры. NET'овскую надстройку, я думаю, тоже.


DR>Только, далеко не факт, что ценности этих не-ламеров совпадают с вашими.


Этот господин Jolly Roger уж очень себя любит и в оскорбительном тоне участвует в обсуждениях. Он обычно изначально уверен в совершенстве мелкософтовских технологий, практически задом своим отвечает
Re[6]: Утечки памяти?
От: Flammable Россия  
Дата: 29.09.10 11:37
Оценка:
Здравствуйте, Jesmus, Вы писали:

J>Здравствуйте, Flammable, Вы писали:


F>>Вот полный код метода:



J>1) Повесить using на создание reader, убрать Close().

J>2) Этот код будет падать (NullReferenceException) если в каталоге нет ни одного файла с нужной маской (на MapID.Close()).
J>3) MapName не чистится в каждой итерации цикла — в итоге MapNames[] может оказаться заполнен мусорными значениями с прошлых итераций (в первом файле texture была, в остальных нет)
J>4) DoEvents действительно здесь нужна? Просто практика показывает что от этого метода проблема ой как много, а нужен он ой как редко.

2. В каталоге всегда есть файлы Хотя, чем черт не шутит. Надо и это предусмотреть, спасибо.
3. Разве присваивание переменной нового значения не удаляет старое?
4. DoEvents действительно нужна, иначе форма зависает. Файлы объемные, читаются не моментально. А что за проблемы с этим методом?
Re[17]: Утечки памяти?
От: Jolly Roger  
Дата: 29.09.10 11:50
Оценка:
Здравствуйте, v.a.v, Вы писали:

VAV>Вы были правы, что станицы могут не удаляться из рабочего набора, сразу после их освобождения процессом.


Может да, а может нет В принципе, обнуление страницы может быть выполнено и без удаления из рабочего набора процесса, в системе есть функция для быстрого обнуления страниц, что-то вроде MmZeroInPage или похоже. Но и для противоположного мнения можно найти аргументы. В любом случае, точный ответ знают только разработчики. Но ведь с точки зрения прикладного кода это и не суть важно. Важно то, что мы имеем дело с виртуальной памятью, а отображением её на физическую полностью заведует система. Есть, правда, исключение в виде VirtualLock, но это именнно что исключение.
"Нормальные герои всегда идут в обход!"
Re[18]: Утечки памяти?
От: Jolly Roger  
Дата: 29.09.10 11:53
Оценка:
Здравствуйте, Jolly Roger, Вы писали:

А вообще надо-бы мне как-нибудь освежить в памяти Соломона-Руссиновича, а то что-то забываться стало. И Вам настоятельно рекомендую
"Нормальные герои всегда идут в обход!"
Re[7]: Утечки памяти?
От: Jesmus Россия  
Дата: 29.09.10 13:27
Оценка: 9 (2)
Здравствуйте, Flammable, Вы писали:

J>>2) Этот код будет падать (NullReferenceException) если в каталоге нет ни одного файла с нужной маской (на MapID.Close()).

J>>3) MapName не чистится в каждой итерации цикла — в итоге MapNames[] может оказаться заполнен мусорными значениями с прошлых итераций (в первом файле texture была, в остальных нет)
J>>4) DoEvents действительно здесь нужна? Просто практика показывает что от этого метода проблема ой как много, а нужен он ой как редко.

F>2. В каталоге всегда есть файлы Хотя, чем черт не шутит. Надо и это предусмотреть, спасибо.

F>3. Разве присваивание переменной нового значения не удаляет старое?
F>4. DoEvents действительно нужна, иначе форма зависает. Файлы объемные, читаются не моментально. А что за проблемы с этим методом?

2) Ох, если бы мне за каждое "всегда будет" давали денежку когда в эксплуатации оказывалось что и не всегда, и не будет
3) У тебя проблема что новое значение присваивается не всегда, а только если отработает условный блок. Если ни одной "map" или "texture" в файле нет, то нет присвоения => в переменной значение со старого прохода цикла => в массиве мусор. На "всегда будут эти значения" я уже сверху ответил. Пользователи вообще такие шалуны порой
4) Проблемы синронизации. Код с DoEvents должен быть спроетирован также как код с использование потоков — а почему бы тогда не использовать потоки сразу? И опыт подтверждает — видишь в коде DoEvents — будь готов к проблемам, когда пользователь не там щелкнул, сработало событие таймера и изменило состояние объектов посреди метода и прочие прелести многопоточного программирования. Вот быстро нагуглил несколько статей по поводу DoEvents:

Is DoEvents Evil?
Joel's algorithm is flawed
What is the best way to stop developers from calling System.Windows.Forms.Application.DoEvents()?
Re[8]: Утечки памяти?
От: Flammable Россия  
Дата: 29.09.10 16:30
Оценка:
Здравствуйте, Jesmus, Вы писали:

J>4) Проблемы синронизации. Код с DoEvents должен быть спроетирован также как код с использование потоков — а почему бы тогда не использовать потоки сразу? И опыт подтверждает — видишь в коде DoEvents — будь готов к проблемам, когда пользователь не там щелкнул, сработало событие таймера и изменило состояние объектов посреди метода и прочие прелести многопоточного программирования.


С этим пока проблем нет

Спасибо за разъяснения.
Re[6]: Утечки памяти?
От: Jolly Roger  
Дата: 30.09.10 04:56
Оценка:
Здравствуйте, notacat, Вы писали:

N>Поверьте на слово, что если упорно не закрывать стримы и не освобождать ссылки, то даже диспетчер задач это покажет. И если сделать пример, в котором подозрительные действия выполняются в цикле, и аккуратно просить каждый раз GC все лишнее почистить, то за несколько итераций в диспетчере задач прекрасно видно, течет память или не течет.

N>А вот остальные детали и лечение — это уже конечно не к диспетчеру задач надо обращаться.

Я безусловно и с удовольствием верю Вам на слово, но для приобретения опыта хотелось-бы увидеть явление своими глазами Я вот взял код, приведённый ТС, и запустил его без единого изменения на директории с 1000-й файлов, и даже без принудительного вызова GC.Collect. При первом запуске метода объём Working set вырос с 12288 до 14552, а витуальной памяти — с 11600 до 13572. Дальнейшие многократные запуски этого кода не привели к какому-либо росту обоих показателей, они то чуть возрастают, то чуть уменьшаются. Дескрипторы тоже не растут, что по-моему неудивительно, они ведь завёрнуты в SafeHandle, имеющий деструктор, и GC их в своё время закрывает. Я так понимаю, закрывать стрим нужно, чтобы освободить файл немедленно, а иначе он всё равно будет закрыт коллектором, только несколько позже. Я конечно за то, чтобы закрывать такие ресурсы сразу, но и без этого утечки хёндлов в DotNet не будет. Признаться, наблюдаемое поведение совпадает с моими представлениями, но может быть мои представления ошибочны? Как мне увидеть то явление, о котором вы говорили — то есть наблюдаемую в диспетчере ктечку от незакрытых явно стримов?

N>Ну и отдельный вопрос — что половина участников уже забыла, что нужно было топик стартеру. Вы уже все внутренности Windows обсудили, но это не значит, что именно это является обсуждаемым.


Но ведь эта половина не виновата, что данное явление тесно связана с системными сервисами, без знакомства с которыми невозможно правильно расставить акценты Я вот пытался объяснить ему, почему он эти данные не подходят, но видимо безуспешно А судя по раздражённому тону Вашего поста, он не одинок, но разве это моя вина? Может быть, чтобы никого не раздражать, мне следовало поддержать его мнение, хотя я знаю, что это полная чушь? Как Вы считаете?
"Нормальные герои всегда идут в обход!"
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.