Choosing the Right C Run-Time Library for Your Application


Some of the confusion surrounding the use of the CRT libraries in Microsoft Windows development revolves around figuring out which library to use. There are six versions of the library, and they fall into two main categories: debug (DCRT) and release (CRT). In each category is a single-threaded static library, a multithreaded static library, and a multithreaded DLL.

The static versions of the CRT libraries link the library functions directly into your application and are the default versions used for non-MFC-wizard-generated applications. The advantage of using the static versions is that you won't have to ship a CRT library DLL with your product. The disadvantage is that the size of your binary files grows tremendously and your application's working set is much larger. The two static CRT library variants, single-threaded and multithreaded, are self-explanatory. If you're building a DLL and want to use a static CRT library, you should link only with a multithreaded version—if you don't, multithreaded applications can't use your DLL because the single-threaded static CRT libraries aren't thread-safe.

The DLL versions of the CRT libraries, named MSVCRT(D).DLL, allow you to import the CRT libraries' functions. The upside of using these DLLs is that your binary's size is drastically smaller, thus reducing your application's working set. Because other applications are loading the same CRT library DLLs, the operating system can share the page tables for the DLLs' code sections across processes and the entire system will run faster. The downside to using the DLL versions is that you might need to distribute another DLL with your application.

For your applications, it's extremely important that you choose one version of the CRT library to use across all binaries that load into your main program's address space. If you have some DLLs using the static CRT library and others using the DLL CRT library, not only are you making your address space larger with duplicated code, but you're also running the risk of introducing one of the most insidious memory bugs there is—a bug that could take months to track down. If you allocate heap memory out of one DLL and attempt to deallocate that heap memory in another DLL that uses a different version of the CRT library, you can easily crash because the deallocating DLL doesn't know where the allocated memory came from. Don't assume that heap memory is heap memory—having different versions of the CRT library running at the same time means that you have multiple versions of heap memory tracking code.

I always use the DLL versions of the CRT libraries, and I suggest that you do the same. The benefit of shrinking the working set and having smaller main binaries overrides any other considerations. In only a few instances—for example, when I'm developing games, where I'm guaranteed never to need multithreading and where performance is supercritical—do I even consider using the single-threaded static versions to avoid the overhead of the multithreaded locking mechanisms.

I've set up BUGSLAYERUTIL.DLL to use the DLL versions of the CRT libraries. The two extensions I demonstrate in this chapter, MemDumperValidator and MemStress, are also in BUGSLAYERUTIL.DLL. These extensions expect you to be using the DLL versions. If you want to use the extensions in your application but not the DLL versions, however, it's trivial to pull out the source files, MEMDUMPERVALIDATOR.CPP, MEMDUMPERVALIDATOR.H, MEMSTRESS.CPP, MEMSTRESSCONSTANTS.H, and MEMSTRESS.H; change the function linkage specified; and drop them into your application.

I want to mention one additional detail about using BUGSLAYERUTIL.DLL in your projects. You might experience a slowdown in your application depending on how you allocate memory. As part of the MemDumperValidator extension, I turn on all the appropriate flags, including _CRTDBG_CHECK_ALWAYS_DF, in the DCRT library to allow full memory tracking and validation. The _CRTDBG_CHECK_ALWAYS_DF flag tells the DCRT library to walk through and validate each piece of heap memory each time you allocate or deallocate heap memory. If you're doing thousands of small allocations in your application, you'll see the slowdown. This is a perfect indication that you probably need to look at your data algorithms. Doing lots of small allocations is a huge performance problem, so you'll need to fix it. If you can't change the code, you can turn off the flag by calling _CrtSetDbgFlag.




Debugging Applications for Microsoft. NET and Microsoft Windows
Debugging Applications for MicrosoftВ® .NET and Microsoft WindowsВ® (Pro-Developer)
ISBN: 0735615365
EAN: 2147483647
Year: 2003
Pages: 177
Authors: John Robbins

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net