📄 memtrack.htm
字号:
article is intended for device driver developers.</font><br>
<br>
<font color="#000000">A common location for programming
errors in a complex project, be it a driver or a
Win32 program, is in memory usage. Unforuntately,
there do not yet exist any automated error detection
tools for drivers like the ones that are available
for Win32 programs. A single buffer overun, underrun,
leak or double free can cause you to waste hours
painfully tracking down the bug. To address this
in some of my own complex drivers I've developed
a simple set of memory functions that I use in place
of the standard <strong>Ex</strong>-variety. With
them I catch short underrun, overrun, and double
free errors immediately. The functions also tell
me when the system runs out of pool, and keeps track
of how much of each pool my driver has allocated,
along with the high-water marks for the driver's
pool usage. These statistics clearly show me if
my driver is leaking memoy.</font><br>
<br>
<font color="#000000">Another benifit of the memory
tracking functions I've developed is that they are
almost totally disabled in a free build of a driver.
However, their replacements for the <strong>ExInitializeLookasideList</strong>
functions provide a useful service even then. In
NT 4 SP3 Microsoft decided to place lookaside list
depth management under the control of a dynamic
tuning mechanism. Thus, the system ignores the value
you pass in for the depth of the lookaside when
you initialize it, and instead decides, based on
the pattern of allocations and frees you make to
the list, how deep the list should be over time.
If you have a driver that you've tuned to expect
a certain number of entries on a lookaside list
you might be unpleasantly surprised at its performance
under SP3's tuning algorithm. The memory functions
I implement initialize lookaside lists in such a
way that they are kept off of the system tuning
list - the depth you specify is the real depth of
a list and the system will not change it.</font></td>
</tr>
<tr>
<td colspan="3" height="40" valign="middle"><span class='sectionheader'>Using the Memory Tracking Library</span></td>
</tr>
<tr>
<td valign="TOP" colspan="3">To use the library you
first add memtrack.c to your driver's sources file.
In each source file of your driver that you perform
memory allocation or deallocation, include memtrack.h,
and change the <strong>Ex</strong> prefix on the
memory functions you use (<strong>ExAllocatePool</strong>,
<strong>ExFreeToNPagedLookasideList</strong>, etc.)
to <strong>Mem</strong>. Finally, call <strong>MemTrackInit</strong>()
in your <strong>DriverEntry</strong> before any
memory operations are invoked. If you want to see
statistics regarding your drivers usage of paged
and non-paged pool place calls to the <strong>MemTrackPrintStats</strong>
function in appropriate places. <strong>MemTrackPrintStats</strong>
takes one parameter, a text string, that it prints
out to label the statistics, which are presented
as <strong>DbgPrint</strong> output. Here is an
example of the output:
<pre>
Filemon Nonpaged Memory Usage:
Current: 63838 bytes
Max: 127383 bytes
Filemon Paged Memory Usage:
Current: 0 bytes
Max: 0 bytes
</pre>
<p>The way that the memory tracking functions work
is straight-forward. The replacements for the
lookaside list initialization functions, <strong>MemInitializeNPagedLookasideList</strong>
and <strong>MemInitializePagedLookasideList</strong>,
initialize a standard NT lookaside list structure
by-hand, rather than letting the system do it.
This prevents the system from knowing that the
lookaside list exists, and therefore prevents
the system lookaside list tuning algorithms from
affecting the list. The memory allocation functions,
<strong>MemAllocatePool</strong>, and <strong>MemAllocatePoolWithTag</strong>,
use the <strong>ExAllocate</strong> functions
to over-allocate the buffer that the driver requests.
A buffer length signature is placed at the start
and end of the buffer, and a pointer to the position
in the buffer following the first signature is
returned to the driver. When the driver calls
<strong>MemFreePool</strong> the memory tracker
can check to see if the signatures are both in
place, which catches overrun and underrun conditions.
Double frees are caught by placing a "buffer
has been freed" signature in the buffer.
If the driver frees the buffer again (and another
driver hasn't allocated it and overwritten the
signature in the mean-time) the double free will
be detected. </p>
</td>
</tr>
<tr>
<td height="40" colspan="3" valign="middle"><span class='sectionheader'>The Sample</span>
</td>
</tr>
<tr>
<td colspan="3" valign="TOP">I've instrumented <i>Filemon
for Windows NT </i>as a demonstration of the memory
tracking functions and their use. Changing the filemon
driver to use the tracker took only a few minutes.
Use <a href="../../ntw2k/freeware/debugview.shtml">DebugView</a>,
Windbg, or SoftICE to view <em>Filemon</em> using
<strong>MemTrackPrintStats</strong> to show how
much pool it is using.</td>
</tr>
<tr>
<td colspan="3" valign="middle" height="40" align="center">
<p> </p>
<p> </p>
<p><a href="../../publ.shtml"></a><a href="../../files/ntfilmem.zip"><font size="2"
face="arial"><b>Download Instrumented Filemon For NT (324KB)</b></font></a><br>
<br>
<a href="../../files/memtrack.zip"><font size="2" face="arial"><b>Download
memtrack.c and memtrack.h alone (5KB)</b></font></a><br>
<br>
<a href="../../publ.shtml"></a><a href="#top"><b>Back
to Top</b></a> </p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</TD>
</TR>
</TABLE>
<!-- #EndEditable --></td>
</tr>
</table>
</td>
</tr>
</table>
</body>
<!-- #EndTemplate --></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -