Some knowledgeable people posted the following wisdom about delay load. Archived here to share.
The advantages are that dlls get loaded only when they are used, and you can “statically” bind to an import that may not exist at runtime, and as long as you are careful not to call it, the program will still work downlevel.
The disadvantage is:
1) Some DLLs don’t work DelayLoaded (as mentioned in the limitations of LoadLibrary). In particular, any dll that uses __declspec(thread), or any dll that you want to import data from.
2) You can’t call any API that might be delay loaded in your DllMain (since you can’t call LoadLibrary during DllMain). Probably not a big deal since you’re generally not supposed to call any APIs in DllMain.
3) The DLLs in your process are now initialized in random order. There may be some orders that cause bizarre bugs.
4) In particular, if you “statically” bind to a dll, then your dll is uninitialized before that other dll. If you delayload, then you will be uninitialized after your delayloaded dlls.
5) Since DLLs may be loaded “late”, their preferred base address may be used already by stack or heap data, resulting in a rebasing performance penalty that wouldn’t happen if the Dll was loaded at boot.
6) If the LoadLibrary fails for some reason (at the delay loading site), then your program just crashes. You can catch this exception, but it is difficult to recover from and definitely the API callsite that was expecting to make a call into this delayed dll will have no direct way of detecting failures.
The last one is the biggest burden. It can mean random crashes when your app is under stress (because you’re out of memory to load that DLL). Unless your feature is specifically designed to deal with that DLL not loading (and you’d have to put this code around every place where you call a delayed API), you run this random crash risk.
Delay Loading definitely has its uses and its benefits, but the limitations means it is not correct to blindly delayload everything.