Testing for Errors in Accessing and Allocating MemoryUpdated: June 10, 2004 On This Page
IntroductionDrivers often have errors related to memory access and allocation. Such errors can lead to memory corruption and, eventually, system crashes. The most common errors involve:
You should test every driver for such errors before releasing it—even a driver that seem to be working properly. Crashes caused by memory errors can occur long after a driver accesses an invalid location. Corrupted memory can cause errors and crashes in processes that are completely unrelated to the offending driver. The tools and techniques described here can help you uncover problems that might otherwise go undetected. Use Tags When Allocating MemoryUse ExAllocatePoolWithTag, ExAllocatePoolWithQuotaTag, and ExAllocatePoolWithTagPriority to allocate memory in your driver. These routines enable you to assign a one- to four-character tag (a pool tag) to each memory allocation. Make sure that you use unique tags that distinguish your driver from all other drivers in the system. If your driver is large, considering assigning a different tag for each class of memory allocation. Smaller drivers commonly use only a single tag for all allocations. Driver Verifier, GFlags, PoolMon, and PoolTag use these tags in tracking pool allocations. In addition, the debuggers display the tags along with the contents of a buffer. Link Your Driver with Call Usage VerifierCall Usage Verifier (CUV) provides some of the same features as Driver Verifier. It also checks calls to system routines that manipulate spin locks, lists (including lookaside lists), and IRP stack locations to ensure that:
CUV is a static library that links with kernel-mode Windows Driver Model (WDM) drivers. To build a driver with CUV:
To use CUV in testing, run the driver with a debugger attached. CUV requires a debugger to report errors. CUV is available only in the Windows XP and later DDKs. Drivers that are built with CUV can run only on Windows XP and later versions. Avoid building retail drivers with CUV; it can significantly slow the driver. Use Driver VerifierThe best way to find problems related to memory usage is to run Driver Verifier together with CUV. Driver Verifier has four options designed to detect such problems:
When you enable the special memory pool option for a driver, Windows attempts to satisfy all of the driver's memory allocation requests from the special memory pool. The size of the special pool is limited, depending on the amount of physical memory present on the test system. When the special memory pool becomes depleted, Windows allocates memory from the normal pool. When you enable the memory pool tracking option, Driver Verifier:
You should use the special memory pool and memory pool tracking options to test every driver. Memory pool tracking is not used, however, for graphics drivers. Direct memory access (DMA) checking is available on Windows XP and later versions of Windows. When this option is enabled, Driver Verifier checks for a variety of errors related to DMA, such as buffer overruns, errors in buffer allocations, and errors in address mappings. You should use this option on every driver that uses DMA directly, and on all miniport drivers, which might use DMA indirectly through calls to port drivers that use DMA. Like memory pool tracking, DMA checking is not used for graphics drivers. Driver Verifier issues a bug check if the driver fails any of the special memory pool, memory pool tracking, and DMA checks. Driver Verifier can also simulate low resources, thus helping you detect errors that might occur when the driver is unable to allocate all the memory it requests. When this option is enabled, Driver Verifier causes memory allocation requests to fail randomly, starting approximately seven minutes after system startup. On Windows XP and later versions of Windows, the special memory pool, memory pool tracking, and DMA verification options are all part of the standard options in Driver Verifier. That is, they are enabled if you start Driver Verifier from the command line with the /standard parameter or choose "Create standard settings" in the first Driver Verifier Manager dialog box. To enable low resource simulation, you must choose Create Custom Settings in the dialog box or use the /flags 0x4 parameter on the command line. Set Global FlagsThe Global Flags utility (GFlags.exe) controls two features that are useful in testing for memory usage problems:
When you enable the pool tagging option, Windows collects data and calculates statistics about pool memory allocations. You can display this data using PoolMon or PoolTag. The kernel special pool tag options control whether Driver Verifier performs overrun or underrun detection on memory that has been allocated from the special pool. In addition, you can use these options to request that all memory allocations with a specified tag or size range come from the special pool. The easiest way to enable GFlags options is to start GFlags from the command line and then use the dialog box as follows:
The options do not take effect until you restart the target system. GFlags and Driver Verifier overlap in their use of the special memory pool. If you use both tools to set special memory pool options, Windows will try to use the special pool for any allocation request that matches the specified pool tag or size or is from the driver being verified. If your driver does not allocate large amounts of memory, using Driver Verifier to allocate all requests from special pool is probably adequate; setting allocations based on a specific tag or size is probably unnecessary. However, if you have a large driver that requests a lot of memory, consider using several pool tags in the driver and activating them one at a time with GFlags. Limiting the allocations from the special pool in this way can help to prevent the pool's depletion, thus ensuring that you test all memory allocations. Monitor Tagged Memory Allocations with PoolMon and PoolTagPoolMon and PoolTag display data about tagged memory allocations. PoolMon runs in a command window, and PoolTag is a GUI-based version of the same tool. You can run PoolMon and PoolTag for long periods of time while your driver operates—even as it runs with Driver Verifier—to display data about memory allocations. This data can help you find memory leaks. If you suspect problems with a particular memory allocation, you can use these tools to monitor only that allocation. Note: Combining TechniquesThe best way to test for possible memory access problems is to combine these techniques. For example:
On Windows XP and Windows Server 2003, you should perform at least two test cycles. During the first cycle, perform the steps in the preceding list. During the second cycle, disable the special memory pool option in Driver Verifier, and then run PoolMon or PoolTag to check for memory leaks in tagged allocations. Resources |