1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- Created by texi2html 1.64 -->
<!--
Written by: Lionel Cons <Lionel.Cons@cern.ch> (original author)
Karl Berry <karl@freefriends.org>
Olaf Bachmann <obachman@mathematik.uni-kl.de>
and many others.
Maintained by: Olaf Bachmann <obachman@mathematik.uni-kl.de>
Send bugs and suggestions to <texi2html@mathematik.uni-kl.de>
-->
<HTML>
<HEAD>
<TITLE>Crystal Space: Memory Debugger Internals</TITLE>
<META NAME="description" CONTENT="Crystal Space: Memory Debugger Internals">
<META NAME="keywords" CONTENT="Crystal Space: Memory Debugger Internals">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<META NAME="Generator" CONTENT="texi2html 1.64">
</HEAD>
<BODY LANG="" BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#800080" ALINK="#FF0000">
<A NAME="SEC636"></A>
<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_269.html#SEC635"> < </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_271.html#SEC637"> > </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_263.html#SEC629"> << </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_267.html#SEC633"> Up </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_271.html#SEC637"> >> </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="index.html#SEC_Top">Top</A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_toc.html#SEC_Contents">Contents</A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_285.html#SEC711">Index</A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_abt.html#SEC_About"> ? </A>]</TD>
</TR></TABLE>
<HR SIZE=1>
<H3> 8.4.3 How It Works </H3>
<!--docid::SEC636::-->
<P>
Here are some technical details about the functioning of the memory debugger.
This can help you understand better how it works, and I think this can help
you use the debugger in a more productive fashion.
</P><P>
In each `<SAMP>new</SAMP>' or `<SAMP>delete</SAMP>' call, we check whenever we have been
initialized. If not, we call the initialization function that parses the
`<TT>.map</TT>' file, sets the debugging options and so on. When program exits
the memory debugger checks for unfreed memory block, displays statistics and
so on. This is done by declaring a dummy static variable at the very end of
memory debugger module and the shutdown function being called from its
destructor.
</P><P>
The only trick used in memory debugger is used to get the address from where
`<SAMP>new</SAMP>' and `<SAMP>delete</SAMP>' have been called. This is a processor-dependent
issue, alas we can't do it in a platform-independent fashion. To support
doing this on different platforms we define a macro called
<CODE>GET_CALL_ADDRESS()</CODE>. We pass the first argument of the procedure we're
invoking <CODE>GET_CALL_ADDRESS()</CODE> from and we get the address from were we
were called in a variable called `<SAMP>addr</SAMP>'.
</P><P>
Here are details on how we're doing it on different platforms:
</P><P>
<DL COMPACT>
<DT><EM>Intel x86</EM>
<DD>These processors use a stack for passing arguments, and the same stack is used
to push the return address. Since all machines uses a top-to-bottom stack
(i.e. stack increases in the direction of lower addresses), and also since
ANSI C standard requires that the addresses of function arguments
increase (that is, if you're defining a function such as `<SAMP>void some(int
a, int b)</SAMP>' you can be absolutely sure that address of `<SAMP>b</SAMP>' is higher than
address of `<SAMP>a</SAMP>'. It is a good guess to suppose that on most computers as
of today upon the invocation of the `<SAMP>new</SAMP>' and `<SAMP>delete</SAMP>' operators the
stack will look like this:
<P>
<TABLE><tr><td> </td><td class=example><pre>+-----------------+ higher addresses
| arg2 | ^
+-----------------+ |
| arg1 | |
+-----------------+ |
| return address | |
+-----------------+ lower addresses
</pre></td></tr></table></P><P>
This means that if we take the address of first argument of the procedure and
go one machine word back, we'll get the address of the function's <EM>return
address</EM> word. Now we peek it from there and we have the return address.
This is embedded into a macro that looks like this:
</P><P>
<TABLE><tr><td> </td><td class=example><pre>#define GET_CALL_ADDRESS(firstarg) \
address addr = ((address*)&firstarg) [-1];
</pre></td></tr></table></P><P>
Where `<SAMP>address</SAMP>' is a shortcut for type `<SAMP>void*</SAMP>'.
</P><P>
<DT><EM>An Almost Cross-Platform Solution</EM>
<DD>Fortunately for us, GCC versions above 2.8.0 have a extremely useful
built-in function called <CODE>__builtin_return_address()</CODE>. If we invoke it
with the argument zero, it returns just what we need; the address from where
our procedure was called. Thus, an almost-cross-platform
<CODE>GET_CALL_ADDRESS()</CODE> is implemented this way:
<P>
<TABLE><tr><td> </td><td class=example><pre>#if (__GNUC__ >= 2) && (__GNUC_MINOR__ >= 8)
# define GET_CALL_ADDRESS(firstarg) \
address addr = (address)__builtin_return_address(0);
#endif
</pre></td></tr></table></P><P>
Thus, if you can't get `<TT>memdbg.sh</TT>' to work, you should find a newer
GCC; this should always help.
</DL>
<A NAME="Contributing"></A>
<HR SIZE=1>
<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_269.html#SEC635"> < </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_271.html#SEC637"> > </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_263.html#SEC629"> << </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_267.html#SEC633"> Up </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_271.html#SEC637"> >> </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="index.html#SEC_Top">Top</A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_toc.html#SEC_Contents">Contents</A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_285.html#SEC711">Index</A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_abt.html#SEC_About"> ? </A>]</TD>
</TR></TABLE>
<BR>
<FONT SIZE="-1">
This document was generated
using <A HREF="http://www.mathematik.uni-kl.de/~obachman/Texi2html
"><I>texi2html</I></A>
</BODY>
</HTML>
|