.NET DLLs Loaded Twice

If, like me, you’re still squeezing yourself into 32-bit Windows processes, you’re probably, also like me, constantly keeping an eye on the virtual address space usage of your application. If you happen to have used something like vmmap to take a peek at your memory contents, maybe you’ve noticed something strange with some .NET assemblies: they’re loaded twice! What’s going on…?

Let’s see how this looks in practice.

I created a .NET 3.5 app that does nothing except load a library. The library (doublelib.dll) contains a class, so we can reference it from the app, and a large uncompressed 24-bit BMP to waste a bit of space. In real life you’ll find lots and lots of code will also serve to waste space.

vmmap screenshot
vmmap screenshot

If we ramp up vmmap and select the Images type, we can clearly see the 1.6mb DLL loaded twice. Click on the image for the full size screen shot.

You’ll notice that this only affects DLLs that aren’t in the GAC, and only affects .NET 2.0-based apps.

So let’s cut to the chase: there’s a hotfix available, and you can grab it from here: http://support.microsoft.com/kb/981266. It was reported a long time ago on MS Connect, but it seemed as if it had ended up in the wontfix pile… Then suddenly, a few months ago, a fix appeared. The only caveat is that it’s an opt-in thing; I guess this, and the delay, is probably because 2.0 is a “legacy” – although still officially supported – version of the runtime. MS seem reluctant to mess with what’s broadly working.

So, if you’re squeezed for memory, give the hotfix a try and reclaim your address space…!

Postscript

There’s a terrible bit of advice/misinformation on that KB page about the hotfix. It suggests one of the fixes is to:

Run the application on a 64-bit operating system. 64-bit operating systems have a large virtual address space.

This might be true for a 64-bit process on a 64-bit OS (where it’ll get a whopping 16TB), but in the case of a 32-bit app (which is specifically what the bug affects), you’re only going to get a relatively small amount of additional address space by running on 64-bit Windows; in the realm of a few hundred extra MB out of a theoretical maximum (excluding use of special switches) of 2GB.

  • Brian

    To be fair a large address aware 32 bit application will get the entire 4 gb address space on 64 bit Windows. That’s a significant improvement over running the same process on 32 bit.

  • Yeah, I was thinking of a “vanilla” 32bit process, just run as-is. If you want to make the app aware of the platform, there are a few options, AWE, PAE etc.

  • Arseny Kapoulkine

    LAA does not require any platform-specific code though – it just requires all the code in your application to work well with pointer MSB of 1. Most code handles this well – so you get (something close to) +2 Gb of address space on a 64-bit OS for little effort.

  • CPU set up will JIT to 64 bit concept when loaded into 64 bit process and 32 bit when loaded into a 32 bit process.