Есть идеи о том, как написать правило статического анализа (FxCop), чтобы гарантировать удаление делегатов события

StackOverflow https://stackoverflow.com/questions/854716

Вопрос

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

Есть ли у кого-нибудь какие-либо идеи относительно того, как написать правило в FxCop, чтобы гарантировать удаление наших делегатов из обработчиков?

Я только что видел это и поэтому я попрошу там больше информации.

Это было полезно?

Решение

Хорошо, помимо проблемы реализации фактической проверки (на мой взгляд, это очень похоже на покрытие пути и, следовательно, непрактично) - вот способ написать новое правило FxCop, которое:

Сначала несколько статей, которые помогли мне когда-то:

В реализации простого правила нет ничего особенного.В вашем проекте вам нужен файл Rules.xml в качестве встроенного ресурса (см. здесь).Вы производите свой класс от BaseIntrospectionRule и добавьте свой код в Check()-метод:

public override ProblemCollection Check( TypeNode typeNode )
{
  if( type.IsPublic )
  {
    Problems.Add( new Problem( ... ) );
  }
  return Problems;
}

Я делал это несколько раз назад.Я надеюсь, что это все еще работает, как описано :)

Другие советы

Вам нужно быть более конкретным.Вам не нужно проверять, что ВСЕ делегаты события были отписаны, потому что в обычном случае подписчик живет короче, чем издатель.И утечка памяти происходит только тогда, когда ваш подписчик кажется более долговечным, чем издатель, следовательно, существует ссылка, которая не позволяет GC собирать объект publisher.

Теперь нам нужно убедиться, что если вы подписываетесь на событие на относительно недолговечном объекте, вы в конечном итоге отписываетесь от него.

Эвристика, которую я могу придумать в этом случае:проанализируйте все объекты с локальной переменной (область действия которых ограничена текущим блоком кода {}) и все объекты, которыми вы явно распоряжаетесь.Для каждого события на этих объектах подсчитайте, сколько раз вы подписывались на них и сколько раз вы отказывались от подписки.Если первое число больше, то выдается предупреждение.

Конечно, это не охватывает все случаи, но я думаю, что никакой статический подход не может охватить все случаи в этой задаче, вам нужен какой-то достаточно хороший метод.

Я не буду здесь упоминать преимущества динамического анализа и обзоров кода, поскольку это отдельная тема, не имеющая отношения к данному вопросу.

Можете ли вы принудительно ввести правило, согласно которому все подписки на события должны обрабатываться через WeakReferences?Я думаю, что это должно быть проще реализовать, чем анализировать фактический поток работы вашей программы.

Безопасно ли предполагать, что объекты, реализующие обработчики, каким-то образом имеют ссылки на объект с событиями?Если это так, то вам лучше выяснить, как разорвать порочный круг другим способом.

Некоторое время назад у нас происходило нечто подобное с обработчиками событий на ASP.NET страницах.Объекты, в которых реализованы обработчики, также имели ссылки на страницы.После того, как мы разбили архитектурно столько ссылок, сколько смогли, несколько оставшихся были заменены на WeakReferences .Больше никаких проблем с памятью!

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top