Microsoft Engineer Reveals How Bad Code Slows Down and Crashes Your PC

A recent investigation by Microsoft engineers has spotlighted a significant memory leak issue affecting .NET applications on Windows, particularly after upgrading to .NET 7 or newer.

The root cause? Improper use of the reloadOnChange parameter in the Microsoft.Extensions.Configuration APIs—a seemingly innocuous setting that can quietly cripple application performance and stability over time.

The reloadOnChange parameter, when set to true, instructs the application to monitor configuration files (such as appsettings.json) for changes and reload them dynamically.

While this feature enables real-time configuration updates without restarting the application, its misuse—especially when invoked repeatedly in application code—leads to a gradual and persistent increase in memory usage.

This can ultimately result in OutOfMemoryException errors and severe performance degradation.

Technical Deep Dive: How the Leak Manifests

The problem arises from how .NET handles file monitoring on Windows. When reloadOnChange is enabled and IConfigurationBuilder.Build() is called, the framework internally creates a FileSystemWatcher monitor to monitor the specified file.

Each invocation allocates an 8KB System.Byte[] buffer, which is pinned in memory for use by the Windows API function ReadDirectoryChangesW:

csharpIConfiguration configuration = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
    .Build();
var someConfig = configuration["someConfig"];

The signature of the underlying Windows API call is:

cBOOL ReadDirectoryChangesW(
    HANDLE hDirectory,
    LPVOID lpBuffer,
    DWORD nBufferLength,
    BOOL bWatchSubtree,
    DWORD dwNotifyFilter,
    LPDWORD lpBytesReturned,
    LPOVERLAPPED lpOverlapped,
    LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);

The buffer passed as lpBuffer must be pinned, preventing the garbage collector from relocating it.

Over time, as more such pinned buffers accumulate, especially if the configuration builder is invoked in frequently executed code paths like controller actions or middleware, memory fragmentation increases.

This leads to large portions of the managed heap (particularly Generation 2) becoming unusable, as pinned objects block memory compaction and reuse.

Diagnostic commands such as !gcheapstat and !dumpheap in WinDbg, or equivalent commands in dotnet-dump, reveal a growing number of System.IO.FileSystemWatcher+AsyncReadState objects and pinned System.Byte[] arrays.

These objects persist in memory, causing heap fragmentation and a steady rise in committed memory, with much of it left as unusable free space.

Best Practices and Remediation Steps

Microsoft engineers emphasize that reloadOnChange: true should only be used during application startup, ideally once, to set up configuration monitoring.

Most ASP.NET Core apps already load and monitor standard configuration files automatically, making additional manual monitoring unnecessary. Repeatedly calling Build() with reloadOnChange: true In runtime, code is a common mistake that triggers the leak.

To prevent or resolve this issue:

  • Restrict Use of reloadOnChange: Only enable it during application startup, not in runtime logic or per-request code.
  • Leverage Dependency Injection: Access configuration data via dependency injection rather than rebuilding configuration objects repeatedly.
  • Set reloadOnChange: false for Dynamic Loads: If dynamic loading is unavoidable, ensure reloadOnChange is set to false to avoid unnecessary file monitoring and buffer pinning.
  • Monitor Memory Usage: Use tools like dotnet-counters, dotnet-dump, and Visual Studio diagnostics to detect early signs of memory leaks and fragmentation.

By adhering to these practices, developers can avoid subtle but devastating memory leaks that undermine .NET application reliability on Windows.

This issue underscores the importance of understanding the technical implications of framework features and the need for vigilance when updating application dependencies or coding patterns.

Find this Story Interesting! Follow us on LinkedIn and X to Get More Instant updates

AnuPriya
AnuPriya
Any Priya is a cybersecurity reporter at Cyber Press, specializing in cyber attacks, dark web monitoring, data breaches, vulnerabilities, and malware. She delivers in-depth analysis on emerging threats and digital security trends.

Trending News

Related Stories