Yesterday a developer in my group came by asking about a failure he saw when running the application verifier on his component. The app verifier was reporting that he was using a HEAP_NO_SERIALIZE heap from a thread other than the one that created the heap.
I looked a bit deeper and realized that he was running with the single threaded statically linked C runtime library. An honest mistake, given that it’s the default version of the C runtime library.
You see, there are 3 different versions of the C runtime library shipped (and 3 different versions of the ATL and MFC libraries too).
The first is the statically linked single-threaded library. This one can be used only on single threaded applications, and all the object code for the C runtime library functions used is included in the application binary. You get this with the /ML compiler switch.
The second is the statically linked, multi-threaded library. This one’s the same as the first, but you can use it in a multithreaded application. You get this one with the /MT compiler switch.
The third is the dynamically linked library. This one keeps all the C runtime library code in a separate DLL (MSVCRTxx.DLL). Since the runtime library code’s in a DLL, it also handles multi-threaded issues. The DLL library is enabled with the /MD switch.
But I’ve been wondering. Why on earth would anyone ever choose any option OTHER than multi-threaded DLL version of the runtime library?
There are LOTS of reasons for always using the multithreaded DLL:
1) Your application is smaller because it doesn’t have the C runtime library loaded into it.
2) Because of #1, your application will load faster. The C runtime library is almost certainly in memory, so the pages containing the library don’t have to be read from disk.
3) Using the multithreaded DLL future-proofs your application. If you ever add a second thread to your application (or call into an API that creates multiple threads), you don’t have to remember to change your C runtime library. And unless you’re running the app verifier regularly, the only way you’ll find out about the problem is if you get a heap corruption (if you’re lucky).
4) If your application has multiple DLL’s, then you need to be VERY careful about allocation – each DLL will have its own C runtime library heap, as will the application. If you allocate a block in one DLL, you must free it in the same DLL.
5) If a security bug is ever found in the C runtime library, you don’t have to release an update to your app.
The last one’s probably the most important IMHO. Just to be clear – There haven’t been any security holes found in the C runtime library. But it could happen. And when it happens, it’s pretty ugly. A really good example of this can be seen with the security vulnerability that was found in the zlib compression library. This library was shipped in dozens of products, and every single one of them had to be updated. If you do a google search for “zlib library security vulnerability” you can see some of the chaos that resulted from this disclosure. If your app used the DLL C runtime library, then you’d get the security fix for free from windows update when Microsoft posted the update.
The only arguments I’ve been able to come up with for using the static C runtime libraries are:
1) I don’t have to distribute two binaries with my application – If I use the DLL, I need to redistribute the DLL. This makes my application setup more complicated.
Yes, but not significantly (IMHO). This page lists the redistribution info for the C runtime library and other components.
2) If I statically link to the C runtime library, I avoid DLL hell.
This is a red herring IMHO. Ever since VC6, the C runtime library has been tightly versioned, as long as your installer follows the rules for version checking of redistributable files (found here) you should be ok.
3) My code is faster since the C runtime library doesn’t have to do all that heap synchronization stuff.
Is it really? How much checking is involved in the multithreaded library? Let’s see. The multithreaded library puts some stuff that was kept in global variable in thread local storage. So there’s an extra memory indirection involved on routines like strtok etc. Also, the single threaded library creates it’s heap with HEAP_NO_SERIALIZE (that’s what led to this entire post J). But that just wraps the heap access with an EnterCriticalSection/ExitCriticalSection. Which is very very fast if there’s no contention. And since this is a single threaded application, by definition there’s no contention for the critical section.
Using the multithreaded DLL C runtime library is especially important for systems programmers. First off, if your system component is a DLL, it’s pretty safe to assume that you’ll be called from multiple threads, so at an absolute minimum, you’re going to want to use the multithreaded static C runtime library. And if you’re using the multithreaded static C runtime library, why NOT use the DLL version?
If you’re not writing a DLL, then it’s highly likely that your app does (or will) use multiple threads. Which brings me back to the previous comment – why NOT use the DLL version?
You’re app will be smaller, more secure, future-proof, and no slower than if you don’t.