Утечки памяти Вопросы .net - PullRequest
0 голосов
/ 26 января 2012

Я немного озадачен правильным способом написания кода.Я прочитал, что мне не нужно хранить ссылки на переменные, потому что сборка мусора не очищает его, но я не понял несколько вещей.

  1. Что насчет этого кода:

    private List<String> foo;
    
    public List<String> bar ()
    {
        foo = new List<String>();
        foo.add(something);
        return foo;
    }
    

Каждый раз, когда я вызываю метод bar, список old foo теряет ссылку, и она будет кандидатом на сборку мусора?Должен ли я объявить ( и инициализировать ???? ) большую часть переменной в начале класса и использовать после или объявить до и инициализировать внутри метода?

2.Как насчет удаленного объекта?Если я напишу этот код

private void browser_navigating(Object sender, NavigatingEventargs e)
{
    Uri someurl = new URI(something);
    List<String> somelist = new List<String>();
}

Если у меня есть 20 объектов webBrowser, которые используют событие навигации, они создают Uri и List, когда событие навигации запускается, верно?Но что происходит с объектом внутри события, когда я располагаю webBrowser?Они потеряют ссылку?Когда я распоряжаюсь чем-то, это работает для всех его детей, но работает ли оно и для тех объектов, которые не реализуют iDisposable (таких как Uri и List), поэтому они будут очищены от мусора или останутся в памяти?

2.1.Эти события автоматически регистрируются после того, как объект, который его зарегистрировал, удаляется?

3) Я прочитал, что статические объекты - это проблема утечек памяти.Как насчет того, если мне нужно использовать класс много раз, и я должен создавать его каждый раз, когда мне нужно объявить его статическим (например, в моем случае у меня есть класс статического соединения, который внутри имеет методы для входа и связи с веб-сервером, я объявляюstatic (в моем классе mainWinform), потому что я храню в нем файлы cookie, полученные от входа в систему)

Я буду благодарен вам, кто мог ответить на мои вопросы.

Ответы [ 2 ]

1 голос
/ 26 января 2012

1: я должен объявить (и инициализировать ????) большую часть переменной в начале класса и использовать после или объявить до и инициализировать внутри метода?

Как правило, объект должен выходить из области видимости, как только вы закончите с ним. Поэтому, если он используется только внутри метода, он должен быть локальным для этого метода. Чем дольше объект живет, тем более вероятно, что он будет повышен до уровня кучи. Сбор данных в старших поколениях обходится дороже и собирается гораздо реже. Таким образом, выведение объектов из области видимости как можно скорее приведет к снижению потребления памяти, а также позволит вашей программе работать быстрее.

2: Но что происходит с объектом внутри события, когда я удаляю веб-браузер? Они потеряют ссылку? Когда я располагаю что-то, это работает для всех его детей, но работает ли оно и для тех объектов, которые не реализуют iDisposable (таких как Uri и List), так что они будут очищены от мусора или останутся в памяти?

Когда вы избавляетесь от объекта, он фактически мертв для мира. Любой другой, у кого есть ссылка на него, все еще будет иметь эту ссылку, но объект будет (или должен в любом случае) поднять ObjectDisposedException, если они попытаются что-то с ним сделать.

Неуправляемые ресурсы объекта (дескрипторы файлов, соединения и т. Д.) Освобождаются сразу после его удаления. Его неуправляемые ресурсы обычно очищаются сборщиком мусора. Поэтому они не будут очищены до тех пор, пока последняя ссылка на этот объект не выйдет из области видимости.

3) Я прочитал, что статические объекты - это проблема утечек памяти.

Это потому, что статические поля класса никогда не выйдут из области видимости. Поэтому любые данные, на которые они ссылаются, не могут быть очищены, если вы явно не установите для них ссылку null или не замените ее чем-то другим.

Гораздо лучше обрабатывать каждый сеанс с веб-сервером отдельно. Это не только помогает сборщику мусора убирать за вами, но также позволяет выполнять такие действия, как проведение более одного одновременного сеанса.

0 голосов
/ 26 января 2012

Каждый раз, когда я вызываю метод bar, старый список foo теряет ссылку, и она будет кандидатом на сборку мусора?

Это потенциально верно. Назначение foo = new List<String> заставляет foo перестать указывать на предыдущее значение List<string>. Если бы foo было только ссылкой на этот объект, тогда он был бы доступен для сбора. Однако, если другая функция в вашем типе выставила объект, он, возможно, все еще был бы жив. Например

List<string> GetFoo() {  
  return foo;
}

Я прочитал, что статические объекты - это проблема утечек памяти

Это частично верно. Утечка памяти происходит в .Net, когда ссылка на объект удерживается корнем GC после того, как он больше не используется. Статическое поле - это корень GC, и это трудный путь, потому что он не исчезает, как локальная переменная. Статическое поле по существу держит объект в памяти навсегда.

class Holder {
  public static List<string> StaticField;
}

Holder.StaticField = GetFoo();  

На List<string>, изначально сохраненный в foo, теперь ссылается StaticField. До тех пор, пока StaticField не будет указан другой объект, он будет хранить List<string> в памяти до конца программы

...