File: cs_270.html

package info (click to toggle)
crystalspace 0.94-20020412-3
  • links: PTS
  • area: main
  • in suites: woody
  • size: 62,276 kB
  • ctags: 52,843
  • sloc: cpp: 274,783; ansic: 6,608; perl: 6,276; objc: 3,952; asm: 2,942; python: 2,354; php: 542; pascal: 530; sh: 430; makefile: 370; awk: 193
file content (142 lines) | stat: -rw-r--r-- 6,821 bytes parent folder | download
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"> &lt; </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_271.html#SEC637"> &gt; </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT"> &nbsp; <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_263.html#SEC629"> &lt;&lt; </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"> &gt;&gt; </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT"> &nbsp; <TD VALIGN="MIDDLE" ALIGN="LEFT"> &nbsp; <TD VALIGN="MIDDLE" ALIGN="LEFT"> &nbsp; <TD VALIGN="MIDDLE" ALIGN="LEFT"> &nbsp; <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>&nbsp;</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>&nbsp;</td><td class=example><pre>#define GET_CALL_ADDRESS(firstarg) \
  address addr = ((address*)&#38;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>&nbsp;</td><td class=example><pre>#if (__GNUC__ &#62;= 2) &#38;&#38; (__GNUC_MINOR__ &#62;= 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"> &lt; </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_271.html#SEC637"> &gt; </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT"> &nbsp; <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_263.html#SEC629"> &lt;&lt; </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"> &gt;&gt; </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT"> &nbsp; <TD VALIGN="MIDDLE" ALIGN="LEFT"> &nbsp; <TD VALIGN="MIDDLE" ALIGN="LEFT"> &nbsp; <TD VALIGN="MIDDLE" ALIGN="LEFT"> &nbsp; <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>