На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
  
> Освобождение памяти
    Ситуация такая: прога открывает файл, он может быть большим, допустим 300 Мб. Читает его в буфер, потом буфер анализирует (просто преобразует байты в числа и заполняет поля некой структуры) и все, потом он не нужен. Но проблема в том, что занятая память не освобождается. Обнуление ссылки и даже ручной вызов сборщика мусора не помогают.
    В конце концов я закомментировал весь код, в котором используется буфер, но ничего не изменилось. Весь этот код находится внутри одной функции, но при выходе из нее память не отдается. Причем если сделать маленький проектик и туда поместить этот код, то ручной вызов мусорщика память таки освобождает. А в большом проекте нет. Из-за чего это может быть? Код всего проекта я конечно не могу сюда кинуть. Да и как остальной код может на что-то влиять, если буфер является локальной переменной в данной функции, которая сейчас содержит только этот код?

    ExpandedWrap disabled
      BinaryReader binReader = new BinaryReader(File.Open(path, FileMode.Open));
      FileInfo fileInfo = new FileInfo(path);
      byte[] buffer = binReader.ReadBytes((int)fileInfo.Length);
      // здесь был код, использующий буфер, но он закомментирован
       
      buffer = null;
      GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);


    При работе проги эта функция может вызываться неоднократно (по отношению к разным файлам) и в конце концов получаем OutOfMemoryException
      Может как-то так
      ExpandedWrap disabled
        using (FileStream fs = File.Open(...
        {
        BinaryReader binReader = new BinaryReader(fs...
         
        }
        В .NET с памятью все не просто. Тут есть пара намеков, как можно ускорить освобождение памяти. Использование using - один из них.

        http://stackoverflow.com/questions/1852929...ry-cleanup-in-c
          Юзай PerfView, возможно остались где то ссылки на буффер твой.
            Цитата Ataru @
            Причем если сделать маленький проектик и туда поместить этот код, то ручной вызов мусорщика память таки освобождает. А в большом проекте нет.

            - Дорогой, вынеси мусор!
            - Сейчас, подземелье с корешами дочистим, и тогда вынесу

            Т.е. сборщик памяти проинформирован, что данная память больше не требуется. Но это вовсе не значит, что он вот прям сейчас всё бросит и пойдёт очищать. Как приводил пример один из столпов NET, в ситуации с бесконечно большой памятью ни сборка мусора, ни финализаторы никогда не будут исполнены - потому что не надо.
              Цитата Mr.Delphist @
              Т.е. сборщик памяти проинформирован, что данная память больше не требуется. Но это вовсе не значит, что он вот прям сейчас всё бросит и пойдёт очищать. Как приводил пример один из столпов NET, в ситуации с бесконечно большой памятью ни сборка мусора, ни финализаторы никогда не будут исполнены - потому что не надо.

              Если бы память была бесконечно большая, то и вопроса бы не возникло. У меня на компе 4 гига, когда одна прога выжрала больше 1 гига, то как бы пора чистить, не? Свободной памяти в этот момент вообще нет, остальное занято виндой и другими программами.

              Добавлено
              Цитата jack128 @
              Юзай PerfView, возможно остались где то ссылки на буффер твой.

              Где могут быть ссылки на буфер, который является локальной переменной в данной функции, весь код которой я привел? Ну binReader.Close() только забыл скопировать.

              Добавлено
              Цитата ter_nk_ @
              Может как-то так
              ExpandedWrap disabled
                using (FileStream fs = File.Open(...
                {
                BinaryReader binReader = new BinaryReader(fs...
                 
                }

              Честно говоря поленился с using экспериментировать. Мне кажется не должно влиять. Проблема ведь в удалении буфера, а не потока. После операции чтения буфер с потоком уже никак не связан. И БинариРидер я у себя закрываю конечно, и ссылку на него обнулял, и Dispose вызывал, все это заменяет using. Ну и потом, раз в тестовой программке память очищается, значит дело не в приведенном коде, а в остальной части проекта. Но скинуть весь проект нет возможности, поэтому я скорее хотел спросить примерно в какую сторону копать.
              Но это ладно, с этим моментом я в итоге разобрался, просто сделал маленький буфер и читаю в него частями. Строго говоря надо было изначально так делать.

              Теперь у меня другое вылезло, тут уж вообще загадка. Есть модуль, экспортирующий данные. Ему передаются ссылки на несколько DataGridView, он перебирает строки и экспортирует их содержимое (в что и как - сейчас не важно). Оказалось, что этот модуль тоже отжирает память и не возвращает после всего. Опять я по максимуму все закомментировал и оказалось, что память жрется вот на этих строках.

              ExpandedWrap disabled
                private void BuildDataRows(ref DataGridView dg)
                {
                    for (int iRow = 0; iRow < dg.Rows.Count; ++iRow)
                    {
                        DataGridViewRow row = dg.Rows[iRow];
                 
                        for (int iCol = 0; iCol < dg.Columns.Count; iCol++)
                        {
                           // тут все закомментировано
                        }
                    }
                }


              DataGridView там конечно очень большой. При отображении таблицы приходится с ним работать в виртуальном режиме, т.е. использовать методы dg_CellValueNeeded. Но почему при переборе строк он съедает всю память и как заставить его ее освободить? Он гигабайт может съесть при вот таком переборе строк и колонок нескольких больших таблиц...
                Цитата Ataru @
                Где могут быть ссылки на буфер, который является локальной переменной в данной функции, весь код которой я привел? Ну binReader.Close() только забыл скопировать.

                Без понятия, я твой проект не щупал. Но PerfView всё покажет.
                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                0 пользователей:


                Рейтинг@Mail.ru
                [ Script execution time: 0,0397 ]   [ 16 queries used ]   [ Generated: 2.05.24, 11:02 GMT ]