← ClaudeAtlas

memory-leaks-and-diagnosticslisted

Review .NET code for managed memory leaks - event handler leaks, static caches, timers, CancellationTokenRegistration, closure captures - and how to diagnose with dotnet-counters/gcdump. Use when reviewing long-lived objects, event subscriptions, or investigating memory growth.
Sarmkadan/dotnet-senior-skills · ★ 0 · AI & Automation · score 72
Install: claude install-skill Sarmkadan/dotnet-senior-skills
# Memory Leaks and Diagnostics ## Managed leaks are reachability bugs The GC collects what is unreachable; a ".NET memory leak" is always something still holding a reference - usually a long-lived object (static, singleton, cache) pointing at things meant to be short-lived. Review long-lived state with one question: "what removes entries from this?" ## Event handlers: the classic `publisher.Event += subscriber.Handler` stores a reference to the subscriber inside the publisher. Long-lived publisher + short-lived subscriber = every subscriber ever, retained: ```csharp // WRONG: scoped service subscribing to a singleton's event - one leaked scope graph per request public OrderProcessor(GlobalEvents events) => events.OrderPlaced += OnOrderPlaced; // RIGHT: unsubscribe symmetrically - which means the type is IDisposable public void Dispose() => _events.OrderPlaced -= OnOrderPlaced; ``` Review flags: any `+=` on an event of a longer-lived object without the matching `-=` in Dispose; `static event` (subscribers live until process exit); lambda subscriptions (`events.X += (s, e) => ...`) that can never be unsubscribed because the delegate instance is gone. Prefer not having the mismatch at all: singleton-to-singleton events are fine; cross-lifetime notification is better served by `Channel<T>`/messaging than events. ## The other repeat offenders - **Static/singleton collections as ad-hoc caches**: `static Dictionary<Guid, UserState>` with adds and no eviction is a leak with a