mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-25 23:10:47 -08:00
429 lines
No EOL
29 KiB
HTML
429 lines
No EOL
29 KiB
HTML
|
|
|
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
|
|
|
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|
|
|
<title>4. Debugging with the Memory Pool System — Memory Pool System 1.111.0 documentation</title>
|
|
|
|
<link rel="stylesheet" href="../_static/mps.css" type="text/css" />
|
|
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
|
|
|
<script type="text/javascript">
|
|
var DOCUMENTATION_OPTIONS = {
|
|
URL_ROOT: '../',
|
|
VERSION: '1.111.0',
|
|
COLLAPSE_INDEX: false,
|
|
FILE_SUFFIX: '.html',
|
|
HAS_SOURCE: true
|
|
};
|
|
</script>
|
|
<script type="text/javascript" src="../_static/jquery.js"></script>
|
|
<script type="text/javascript" src="../_static/underscore.js"></script>
|
|
<script type="text/javascript" src="../_static/doctools.js"></script>
|
|
<link rel="copyright" title="Copyright" href="../copyright.html" />
|
|
<link rel="top" title="Memory Pool System 1.111.0 documentation" href="../index.html" />
|
|
<link rel="up" title="Guide" href="index.html" />
|
|
<link rel="next" title="5. Tuning the Memory Pool System for performance" href="perf.html" />
|
|
<link rel="prev" title="3. Garbage collecting a language with the Memory Pool System" href="lang.html" />
|
|
</head>
|
|
<body>
|
|
<div class="related">
|
|
<h3>Navigation</h3>
|
|
<ul>
|
|
<li class="right" style="margin-right: 10px">
|
|
<a href="../genindex.html" title="General Index"
|
|
accesskey="I">index</a></li>
|
|
<li class="right" >
|
|
<a href="perf.html" title="5. Tuning the Memory Pool System for performance"
|
|
accesskey="N">next</a> |</li>
|
|
<li class="right" >
|
|
<a href="lang.html" title="3. Garbage collecting a language with the Memory Pool System"
|
|
accesskey="P">previous</a> |</li>
|
|
<li><a href="../index.html">Memory Pool System 1.111.0 documentation</a> »</li>
|
|
<li><a href="index.html" accesskey="U">Guide</a> »</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="document">
|
|
<div class="documentwrapper">
|
|
<div class="bodywrapper">
|
|
<div class="body">
|
|
|
|
<div class="section" id="debugging-with-the-memory-pool-system">
|
|
<span id="guide-debug"></span><span id="index-0"></span><h1>4. Debugging with the Memory Pool System<a class="headerlink" href="#debugging-with-the-memory-pool-system" title="Permalink to this headline">¶</a></h1>
|
|
<p>Memory management errors are some of the most stubborn and difficult
|
|
to track down, because the effect so often appears at a distant point
|
|
in the program that is seemingly unrelated to the cause, and by the
|
|
time the error is revealed, the information needed to reconstruct the
|
|
cause has long vanished. Immediately after an <a class="reference internal" href="../glossary/o.html#term-overwriting-error"><em class="xref std std-term">overwriting
|
|
error</em></a>, the block that overran its bounds is fine, and the block that
|
|
was overwritten may not be visited for a long time. A failure to
|
|
<a class="reference internal" href="../glossary/f.html#term-fix"><em class="xref std std-term">fix</em></a> a <a class="reference internal" href="../glossary/r.html#term-reference"><em class="xref std std-term">reference</em></a> does not necessarily cause the object
|
|
pointed to by the missed reference to die immediately: there may be
|
|
other references to that object, or a garbage collection may be
|
|
delayed. And even if it does die, the space it occupies may not be
|
|
re-allocated for some time.</p>
|
|
<div class="section" id="general-debugging-advice">
|
|
<span id="guide-debug-advice"></span><h2>4.1. General debugging advice<a class="headerlink" href="#general-debugging-advice" title="Permalink to this headline">¶</a></h2>
|
|
<ol class="arabic">
|
|
<li><p class="first">Compile with debugging information turned on (<tt class="docutils literal"><span class="pre">-g</span></tt> on the GCC or
|
|
Clang command line).</p>
|
|
</li>
|
|
<li><p id="index-1">Build the <a class="reference internal" href="../glossary/c.html#term-cool"><em class="xref std std-term">cool</em></a> <a class="reference internal" href="../glossary/v.html#term-variety"><em class="xref std std-term">variety</em></a> of the MPS (by defining the
|
|
preprocessor constant <tt class="docutils literal"><span class="pre">CONFIG_VAR_COOL</span></tt>, for example by setting
|
|
<tt class="docutils literal"><span class="pre">-DCONFIG_VAR_COOL</span></tt> on the GCC or Clang command line). This
|
|
variety contains many internal consistency checks (including such
|
|
checks on the <a class="reference internal" href="../glossary/c.html#term-critical-path"><em class="xref std std-term">critical path</em></a>, which make it too slow for use
|
|
in production), and can generate profiling output in the form of
|
|
the <a class="reference internal" href="../glossary/t.html#term-telemetry-stream"><em class="xref std std-term">telemetry stream</em></a>.</p>
|
|
</li>
|
|
<li><p id="index-2">Prepare a reproducible test case if possible. The MPS may be
|
|
<a class="reference internal" href="../glossary/a.html#term-asynchronous-garbage-collector"><em class="xref std std-term">asynchronous</em></a>, but it is
|
|
deterministic, so in single-threaded applications you should be
|
|
able to get consistent results. (But you need to beware of <a class="reference external" href="http://en.wikipedia.org/wiki/Address_space_layout_randomization">address
|
|
space layout randomization</a>: if you perform computation based on
|
|
the addresses of objects, for example, hashing objects by their
|
|
address, then ASLR will cause your hash tables to be laid out
|
|
differently on each run, which may affect the order of memory
|
|
management operations.)</p>
|
|
<p>A fact that assists with reproducibility is that the more
|
|
frequently the collector runs, the sooner and more reliably errors
|
|
are discovered. So if you have a bug that’s hard to reproduce, or
|
|
which manifests itself in different ways on different runs, you may
|
|
be able to provoke it more reliably, or get a more consistent
|
|
result, by having a mode for testing in which you run frequent
|
|
collections (by calling <a class="reference internal" href="../topic/arena.html#mps_arena_collect" title="mps_arena_collect"><tt class="xref c c-func docutils literal"><span class="pre">mps_arena_collect()</span></tt></a> followed by
|
|
<a class="reference internal" href="../topic/arena.html#mps_arena_release" title="mps_arena_release"><tt class="xref c c-func docutils literal"><span class="pre">mps_arena_release()</span></tt></a>), perhaps as frequently as every
|
|
allocation.</p>
|
|
</li>
|
|
<li><p id="index-3">Run your test case inside the debugger. Use <tt class="docutils literal"><span class="pre">assert</span></tt> and
|
|
<tt class="docutils literal"><span class="pre">abort</span></tt> in your error handler (rather than <tt class="docutils literal"><span class="pre">exit</span></tt>) so that you
|
|
can enter the debugger with the contents of the control stack
|
|
available for inspection.</p>
|
|
<p>You may need to make sure that the debugger isn’t entered on
|
|
<a class="reference internal" href="../glossary/b.html#term-barrier-1"><em class="xref std std-term">barrier<sup>(1)</sup></em></a> hits (because the MPS uses barriers to protect
|
|
parts of memory, and barrier hits are common and expected).</p>
|
|
<p>If you are using GDB on OS X, run these commands:</p>
|
|
<div class="highlight-none"><div class="highlight"><pre>set dont-handle-bad-access 1
|
|
handle SIGBUS pass nostop noprint
|
|
</pre></div>
|
|
</div>
|
|
<p>If you are using GDB on Linux, run this command:</p>
|
|
<div class="highlight-none"><div class="highlight"><pre>handle SIGXFSZ pass nostop noprint
|
|
</pre></div>
|
|
</div>
|
|
<p>(On either operating system, you can add these commands to your
|
|
<tt class="docutils literal"><span class="pre">.gdbinit</span></tt> if you always want them to be run.)</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="section" id="example-underscanning">
|
|
<span id="guide-debug-underscanning"></span><span id="index-4"></span><h2>4.2. Example: underscanning<a class="headerlink" href="#example-underscanning" title="Permalink to this headline">¶</a></h2>
|
|
<p>An easy mistake to make is to omit to <a class="reference internal" href="../glossary/f.html#term-fix"><em class="xref std std-term">fix</em></a> a <a class="reference internal" href="../glossary/r.html#term-reference"><em class="xref std std-term">reference</em></a>
|
|
when <a class="reference internal" href="../glossary/s.html#term-scan"><em class="xref std std-term">scanning</em></a> a <a class="reference internal" href="../glossary/f.html#term-formatted-object"><em class="xref std std-term">formatted object</em></a>. For example,
|
|
in the Scheme interpreter’s <a class="reference internal" href="lang.html#guide-lang-scan"><em>scan method</em></a>, I
|
|
might have forgotten to fix the first element of a pair:</p>
|
|
<div class="highlight-c"><div class="highlight"><pre><span class="k">case</span> <span class="n">TYPE_PAIR</span>:
|
|
<span class="hll"> <span class="cm">/* oops, forgot: FIX(CAR(obj)); */</span>
|
|
</span> <span class="n">FIX</span><span class="p">(</span><span class="n">CDR</span><span class="p">(</span><span class="n">obj</span><span class="p">));</span>
|
|
<span class="n">base</span> <span class="o">=</span> <span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">base</span> <span class="o">+</span> <span class="n">ALIGN</span><span class="p">(</span><span class="k">sizeof</span><span class="p">(</span><span class="n">pair_s</span><span class="p">));</span>
|
|
<span class="k">break</span><span class="p">;</span>
|
|
</pre></div>
|
|
</div>
|
|
<p>This means that as far as the MPS is concerned, the first element of
|
|
the pair is <a class="reference internal" href="../glossary/u.html#term-unreachable"><em class="xref std std-term">unreachable</em></a> and so <a class="reference internal" href="../glossary/d.html#term-dead"><em class="xref std std-term">dead</em></a>, so after
|
|
collecting the region of memory containing this object, the space will
|
|
be reused for other objects. So <tt class="docutils literal"><span class="pre">CAR(obj)</span></tt> might end up pointing to
|
|
the start of a valid object (but the wrong one), or to the middle of a
|
|
valid object, or to an unused region of memory, or into an MPS
|
|
internal control structure.</p>
|
|
<p>The reproducible test case is simple. Run a garbage collection by
|
|
calling <tt class="docutils literal"><span class="pre">(gc)</span></tt> and then evaluate any expression:</p>
|
|
<div class="highlight-none"><div class="highlight"><pre>$ gdb ./scheme
|
|
GNU gdb 6.3.50-20050815 (Apple version gdb-1820) (Sat Jun 16 02:40:11 UTC 2012)
|
|
|
|
(gdb) run
|
|
Starting program: example/scheme/scheme
|
|
Reading symbols for shared libraries +............................. done
|
|
MPS Toy Scheme Example
|
|
7944, 0> (gc)
|
|
Collection started.
|
|
Why: Client requests: immediate full collection.
|
|
Clock: 11357
|
|
Collection finished.
|
|
live 1888
|
|
condemned 7968
|
|
not_condemned 0
|
|
clock: 12008
|
|
7968, 1> foo
|
|
Assertion failed: (TYPE(frame) == TYPE_PAIR), function lookup_in_frame, file scheme.c, line 1065.
|
|
|
|
Program received signal SIGABRT, Aborted.
|
|
0x00007fff91aeed46 in __kill ()
|
|
</pre></div>
|
|
</div>
|
|
<p>What’s going on?</p>
|
|
<div class="highlight-none"><div class="highlight"><pre>(gdb) backtrace
|
|
#0 0x00007fff91aeed46 in __kill ()
|
|
#1 0x00007fff90509df0 in abort ()
|
|
#2 0x00007fff9050ae2a in __assert_rtn ()
|
|
#3 0x0000000100003f55 in lookup_in_frame (frame=0x1003fa7d0, symbol=0x1003faf20) at scheme.c:1066
|
|
#4 0x0000000100003ea6 in lookup (env=0x1003fb130, symbol=0x1003faf20) at scheme.c:1087
|
|
#5 0x000000010000341f in eval (env=0x1003fb130, op_env=0x1003fb148, exp=0x1003faf20) at scheme.c:1135
|
|
#6 0x000000010000261b in start (p=0x0, s=0) at scheme.c:3204
|
|
#7 0x0000000100011ded in ProtTramp (resultReturn=0x7fff5fbff7d0, f=0x100002130 <start>, p=0x0, s=0) at protix.c:132
|
|
#8 0x0000000100001ef7 in main (argc=1, argv=0x7fff5fbff830) at scheme.c:3314
|
|
(gdb) frame 4
|
|
#4 0x0000000100003ea6 in lookup (env=0x1003fb130, symbol=0x1003faf20) at scheme.c:1087
|
|
1086 binding = lookup_in_frame(CAR(env), symbol);
|
|
(gdb) print (char *)symbol->symbol.string
|
|
$1 = 0x1003faf30 "foo"
|
|
</pre></div>
|
|
</div>
|
|
<p>The backtrace shows that the interpreter is in the middle of looking
|
|
up the symbol <tt class="docutils literal"><span class="pre">foo</span></tt> in the environment. The Scheme interpreter
|
|
implements the environment as a list of <em>frames</em>, each of which is a
|
|
list of <em>bindings</em>, each binding being a pair of a symbol and its
|
|
value, as shown here:</p>
|
|
<div class="figure align-center">
|
|
<img alt="Diagram: The environment data structure in the Scheme interpreter." src="../_images/scheme-env.svg" /><p class="caption">The environment data structure in the Scheme interpreter.</p>
|
|
</div>
|
|
<p>In this case, because the evaluation is taking place at top level,
|
|
there is only one frame in the environment (the global frame). And
|
|
it’s this frame that’s corrupt:</p>
|
|
<div class="highlight-none"><div class="highlight"><pre>(gdb) frame 3
|
|
#3 0x0000000100003f55 in lookup_in_frame (frame=0x1003fa7d0, symbol=0x1003faf20) at scheme.c:1066
|
|
1066 assert(TYPE(frame) == TYPE_PAIR);
|
|
(gdb) list
|
|
1061 */
|
|
1062
|
|
1063 static obj_t lookup_in_frame(obj_t frame, obj_t symbol)
|
|
1064 {
|
|
1065 while(frame != obj_empty) {
|
|
<span class="hll">1066 assert(TYPE(frame) == TYPE_PAIR);
|
|
</span>1067 assert(TYPE(CAR(frame)) == TYPE_PAIR);
|
|
1068 assert(TYPE(CAAR(frame)) == TYPE_SYMBOL);
|
|
1069 if(CAAR(frame) == symbol)
|
|
1070 return CAR(frame);
|
|
(gdb) print frame->type.type
|
|
$2 = 13
|
|
</pre></div>
|
|
</div>
|
|
<p>The number 13 is the value <tt class="docutils literal"><span class="pre">TYPE_PAD</span></tt>. So instead of the expected
|
|
pair, <tt class="docutils literal"><span class="pre">frame</span></tt> points to a <a class="reference internal" href="../glossary/p.html#term-padding-object"><em class="xref std std-term">padding object</em></a>.</p>
|
|
<p>You might guess at this point that the frame had not been fixed, and
|
|
since you know that the frame is referenced by the <tt class="docutils literal"><span class="pre">car</span></tt> of the
|
|
first pair in the environment, that’s the suspect reference. But in a
|
|
more complex situation this might not yet be clear. In such a
|
|
situation it can be useful to look at the sequence of events leading
|
|
up to the detection of the error. See <a class="reference internal" href="../topic/telemetry.html#topic-telemetry"><em>Telemetry</em></a>.</p>
|
|
</div>
|
|
<div class="section" id="example-allocating-with-wrong-size">
|
|
<span id="guide-debug-size"></span><span id="index-5"></span><h2>4.3. Example: allocating with wrong size<a class="headerlink" href="#example-allocating-with-wrong-size" title="Permalink to this headline">¶</a></h2>
|
|
<p>Here’s another kind of mistake: an off-by-one error in <tt class="docutils literal"><span class="pre">make_string</span></tt>
|
|
leading to the allocation of string objects with the wrong size:</p>
|
|
<div class="highlight-c"><div class="highlight"><pre><span class="k">static</span> <span class="n">obj_t</span> <span class="nf">make_string</span><span class="p">(</span><span class="kt">size_t</span> <span class="n">length</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">string</span><span class="p">)</span>
|
|
<span class="p">{</span>
|
|
<span class="n">obj_t</span> <span class="n">obj</span><span class="p">;</span>
|
|
<span class="n">mps_addr_t</span> <span class="n">addr</span><span class="p">;</span>
|
|
<span class="hll"> <span class="kt">size_t</span> <span class="n">size</span> <span class="o">=</span> <span class="n">ALIGN</span><span class="p">(</span><span class="n">offsetof</span><span class="p">(</span><span class="n">string_s</span><span class="p">,</span> <span class="n">string</span><span class="p">)</span> <span class="o">+</span> <span class="n">length</span><span class="cm">/* oops, forgot: +1 */</span><span class="p">);</span>
|
|
</span> <span class="k">do</span> <span class="p">{</span>
|
|
<span class="n">mps_res_t</span> <span class="n">res</span> <span class="o">=</span> <span class="n">mps_reserve</span><span class="p">(</span><span class="o">&</span><span class="n">addr</span><span class="p">,</span> <span class="n">obj_ap</span><span class="p">,</span> <span class="n">size</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="n">res</span> <span class="o">!=</span> <span class="n">MPS_RES_OK</span><span class="p">)</span> <span class="n">error</span><span class="p">(</span><span class="s">"out of memory in make_string"</span><span class="p">);</span>
|
|
<span class="n">obj</span> <span class="o">=</span> <span class="n">addr</span><span class="p">;</span>
|
|
<span class="n">obj</span><span class="o">-></span><span class="n">string</span><span class="p">.</span><span class="n">type</span> <span class="o">=</span> <span class="n">TYPE_STRING</span><span class="p">;</span>
|
|
<span class="n">obj</span><span class="o">-></span><span class="n">string</span><span class="p">.</span><span class="n">length</span> <span class="o">=</span> <span class="n">length</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="n">string</span><span class="p">)</span> <span class="n">memcpy</span><span class="p">(</span><span class="n">obj</span><span class="o">-></span><span class="n">string</span><span class="p">.</span><span class="n">string</span><span class="p">,</span> <span class="n">string</span><span class="p">,</span> <span class="n">length</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span>
|
|
<span class="k">else</span> <span class="n">memset</span><span class="p">(</span><span class="n">obj</span><span class="o">-></span><span class="n">string</span><span class="p">.</span><span class="n">string</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">length</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span>
|
|
<span class="p">}</span> <span class="k">while</span><span class="p">(</span><span class="o">!</span><span class="n">mps_commit</span><span class="p">(</span><span class="n">obj_ap</span><span class="p">,</span> <span class="n">addr</span><span class="p">,</span> <span class="n">size</span><span class="p">));</span>
|
|
<span class="n">total</span> <span class="o">+=</span> <span class="n">size</span><span class="p">;</span>
|
|
<span class="k">return</span> <span class="n">obj</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
</pre></div>
|
|
</div>
|
|
<p>Here’s a test case that exercises this bug:</p>
|
|
<div class="highlight-scheme"><div class="highlight"><pre><span class="p">(</span><span class="k">define </span><span class="p">(</span><span class="nf">church</span> <span class="nv">n</span> <span class="nv">f</span> <span class="nv">a</span><span class="p">)</span> <span class="p">(</span><span class="k">if </span><span class="p">(</span><span class="nb">eqv? </span><span class="nv">n</span> <span class="mi">0</span><span class="p">)</span> <span class="nv">a</span> <span class="p">(</span><span class="nf">church</span> <span class="p">(</span><span class="nb">- </span><span class="nv">n</span> <span class="mi">1</span><span class="p">)</span> <span class="nv">f</span> <span class="p">(</span><span class="nf">f</span> <span class="nv">a</span><span class="p">))))</span>
|
|
<span class="p">(</span><span class="nf">church</span> <span class="mi">1000</span> <span class="p">(</span><span class="k">lambda </span><span class="p">(</span><span class="nf">s</span><span class="p">)</span> <span class="p">(</span><span class="nb">string-append </span><span class="nv">s</span> <span class="s">"x"</span><span class="p">))</span> <span class="s">""</span><span class="p">)</span>
|
|
</pre></div>
|
|
</div>
|
|
<p>And here’s how it shows up in the debugger:</p>
|
|
<div class="highlight-none"><div class="highlight"><pre>$ gdb ./scheme
|
|
GNU gdb 6.3.50-20050815 (Apple version gdb-1820) (Sat Jun 16 02:40:11 UTC 2012)
|
|
[...]
|
|
(gdb) run < test.scm
|
|
Starting program: example/scheme/scheme < test.scm
|
|
Reading symbols for shared libraries +............................. done
|
|
MPS Toy Scheme Example
|
|
[...]
|
|
9960, 0> church
|
|
Assertion failed: (0), function obj_skip, file scheme.c, line 2940.
|
|
10816, 0>
|
|
Program received signal SIGABRT, Aborted.
|
|
0x00007fff91aeed46 in __kill ()
|
|
(gdb) backtrace
|
|
#0 0x00007fff91aeed46 in __kill ()
|
|
#1 0x00007fff90509df0 in abort ()
|
|
#2 0x00007fff9050ae2a in __assert_rtn ()
|
|
#3 0x00000001000014e3 in obj_skip (base=0x1003f9b88) at scheme.c:2940
|
|
#4 0x0000000100068050 in amcScanNailedOnce (totalReturn=0x7fff5fbfef2c, moreReturn=0x7fff5fbfef28, ss=0x7fff5fbff0a0, pool=0x1003fe278, seg=0x1003fe928, amc=0x1003fe278) at poolamc.c:1485
|
|
#5 0x0000000100067ca1 in amcScanNailed (totalReturn=0x7fff5fbff174, ss=0x7fff5fbff0a0, pool=0x1003fe278, seg=0x1003fe928, amc=0x1003fe278) at poolamc.c:1522
|
|
#6 0x000000010006631f in AMCScan (totalReturn=0x7fff5fbff174, ss=0x7fff5fbff0a0, pool=0x1003fe278, seg=0x1003fe928) at poolamc.c:1595
|
|
#7 0x000000010002686d in PoolScan (totalReturn=0x7fff5fbff174, ss=0x7fff5fbff0a0, pool=0x1003fe278, seg=0x1003fe928) at pool.c:405
|
|
#8 0x0000000100074106 in traceScanSegRes (ts=1, rank=1, arena=0x10012a000, seg=0x1003fe928) at trace.c:1162
|
|
#9 0x000000010002b399 in traceScanSeg (ts=1, rank=1, arena=0x10012a000, seg=0x1003fe928) at trace.c:1222
|
|
#10 0x000000010002d020 in TraceQuantum (trace=0x10012a5a0) at trace.c:1833
|
|
#11 0x000000010001f2d2 in TracePoll (globals=0x10012a000) at trace.c:1981
|
|
#12 0x000000010000d75f in ArenaPoll (globals=0x10012a000) at global.c:684
|
|
#13 0x000000010000ea40 in mps_ap_fill (p_o=0x7fff5fbff3e0, mps_ap=0x1003fe820, size=208) at mpsi.c:961
|
|
#14 0x000000010000447d in make_string (length=190, string=0x0) at scheme.c:468
|
|
#15 0x0000000100008ca2 in entry_string_append (env=0x1003cbe38, op_env=0x1003cbe50, operator=0x1003fad48, operands=0x1003f9af8) at scheme.c:2562
|
|
#16 0x0000000100002fe4 in eval (env=0x1003cbe38, op_env=0x1003cbe50, exp=0x1003f9ae0) at scheme.c:1159
|
|
#17 0x0000000100005ff5 in entry_interpret (env=0x1003cb958, op_env=0x1003cb970, operator=0x1003f99d8, operands=0x1003f9948) at scheme.c:1340
|
|
#18 0x0000000100002fe4 in eval (env=0x1003cb958, op_env=0x1003cb970, exp=0x1003f9878) at scheme.c:1159
|
|
#19 0x000000010000206b in start (p=0x0, s=0) at scheme.c:3213
|
|
#20 0x000000010001287d in ProtTramp (resultReturn=0x7fff5fbff7a0, f=0x100001b80 <start>, p=0x0, s=0) at protix.c:132
|
|
#21 0x0000000100001947 in main (argc=1, argv=0x7fff5fbff808) at scheme.c:3314
|
|
(gdb) frame 3
|
|
#3 0x00000001000014e3 in obj_skip (base=0x1003f9b88) at scheme.c:2940
|
|
2940 assert(0);
|
|
(gdb) list
|
|
2935 break;
|
|
2936 case TYPE_PAD1:
|
|
2937 base = (char *)base + ALIGN(sizeof(pad1_s));
|
|
2938 break;
|
|
2939 default:
|
|
2940 assert(0);
|
|
<span class="hll">2941 fprintf(stderr, "Unexpected object on the heap\n");
|
|
</span>2942 abort();
|
|
2943 return NULL;
|
|
2944 }
|
|
</pre></div>
|
|
</div>
|
|
<p>The object being skipped is corrupt:</p>
|
|
<div class="highlight-none"><div class="highlight"><pre>(gdb) print obj->type.type
|
|
$1 = 4168560
|
|
</pre></div>
|
|
</div>
|
|
<p>What happened to it? It’s often helpful in these situations to have a
|
|
look at nearby memory.</p>
|
|
<div class="highlight-none"><div class="highlight"><pre>(gdb) x/20g obj
|
|
0x1003f9b88: 0x00000001003f9b70 0x00000001003fb000
|
|
0x1003f9b98: 0x0000000000000000 0x00000001003f9c90
|
|
0x1003f9ba8: 0x00000001003fb130 0x0000000000000000
|
|
0x1003f9bb8: 0x00000001003fb000 0x00000001003fb148
|
|
0x1003f9bc8: 0x0000000000000000 0x00000001003f9730
|
|
0x1003f9bd8: 0x00000001003f9a58 0x0000000000000000
|
|
0x1003f9be8: 0x00000001003f9bc8 0x00000001003fb000
|
|
0x1003f9bf8: 0x0000000000000000 0x00000001003fb0a0
|
|
0x1003f9c08: 0x00000001003f9b40 0x0000000000000004
|
|
0x1003f9c18: 0x000000010007b14a 0x0000000100005e30
|
|
</pre></div>
|
|
</div>
|
|
<p>You can see that this is a block containing mostly pairs (which have
|
|
tag 0 and consist of three words), though you can see an operator
|
|
(with tag 4) near the bottom. But what’s that at the start of the
|
|
block, where <tt class="docutils literal"><span class="pre">obj</span></tt>‘s tag should be? It looks like a pointer. So
|
|
what’s in the memory just below <tt class="docutils literal"><span class="pre">obj</span></tt>? Let’s look at the previous
|
|
few words:</p>
|
|
<div class="highlight-none"><div class="highlight"><pre>(gdb) x/10g (mps_word_t*)obj-8
|
|
0x1003f9b48: 0x00000001003f9ae0 0x00000001003fb000
|
|
0x1003f9b58: 0x0000000000000000 0x00000001003f9a80
|
|
0x1003f9b68: 0x00000001003f9b80 0x0000000000000005
|
|
0x1003f9b78: 0x0000000000000000 0x0000000000000000
|
|
0x1003f9b88: 0x00000001003f9b70 0x00000001003fb000
|
|
</pre></div>
|
|
</div>
|
|
<p>Yes: there’s a pair (with tag 0) at <tt class="docutils literal"><span class="pre">0x1003f9b80</span></tt>. So it looks as
|
|
though the previous object was allocated with one size, but skipped
|
|
with a different size. The previous object being the string (with tag
|
|
5) at <tt class="docutils literal"><span class="pre">0x1003f9b70</span></tt> which has length 0 and so is three words long as
|
|
far as <tt class="docutils literal"><span class="pre">obj_skip</span></tt> is concerned:</p>
|
|
<div class="highlight-none"><div class="highlight"><pre>(gdb) print obj_skip(0x1003f9b70)
|
|
$2 = (mps_addr_t) 0x1003f9b88
|
|
</pre></div>
|
|
</div>
|
|
<p>but the next object (the pair) was clearly allocated at
|
|
<tt class="docutils literal"><span class="pre">0x1003f9b80</span></tt> (overwriting the last word of the string), so the
|
|
string must have been allocated with a size of only two words. This
|
|
should be enough evidence to track down the cause.</p>
|
|
</div>
|
|
<div class="section" id="what-next">
|
|
<h2>4.4. What next?<a class="headerlink" href="#what-next" title="Permalink to this headline">¶</a></h2>
|
|
<p>If you tracked down all your bugs, then the next step is the chapter
|
|
<a class="reference internal" href="perf.html#guide-perf"><em>Tuning the Memory Pool System for performance</em></a>.</p>
|
|
<p>But if you’re still struggling, please <a class="reference internal" href="../contact.html#contact"><em>contact us</em></a> and
|
|
see if we can help.</p>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sphinxsidebar">
|
|
<div class="sphinxsidebarwrapper">
|
|
<p class="logo"><a href="../index.html">
|
|
<img class="logo" src="../_static/logo.png" alt="Logo"/>
|
|
</a></p>
|
|
<h3><a href="../index.html">Table Of Contents</a></h3>
|
|
<ul>
|
|
<li><a class="reference internal" href="#">4. Debugging with the Memory Pool System</a><ul>
|
|
<li><a class="reference internal" href="#general-debugging-advice">4.1. General debugging advice</a></li>
|
|
<li><a class="reference internal" href="#example-underscanning">4.2. Example: underscanning</a></li>
|
|
<li><a class="reference internal" href="#example-allocating-with-wrong-size">4.3. Example: allocating with wrong size</a></li>
|
|
<li><a class="reference internal" href="#what-next">4.4. What next?</a></li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
|
|
<h4>Previous topic</h4>
|
|
<p class="topless"><a href="lang.html"
|
|
title="previous chapter">3. Garbage collecting a language with the Memory Pool System</a></p>
|
|
<h4>Next topic</h4>
|
|
<p class="topless"><a href="perf.html"
|
|
title="next chapter">5. Tuning the Memory Pool System for performance</a></p><h4>Downloads</h4>
|
|
|
|
<p class="topless">
|
|
<a href="http://www.ravenbrook.com/project/mps/release/1.111.0/">MPS Kit release 1.111.0</a><br>
|
|
<a href="http://www.ravenbrook.com/project/mps/release/">All MPS Kit releases</a>
|
|
</p>
|
|
|
|
<h4>Issues</h4>
|
|
|
|
<p class="topless">
|
|
<a href="http://www.ravenbrook.com/project/mps/issue/?action=list&view=status%3dopen&display=Job:Priority:Title&sort=Priority">Known issues</a><br>
|
|
<a href="http://www.ravenbrook.com/project/mps/issue/?action=fixed&release_fixed=1.111.0">Issues fixed in release 1.111.0</a>
|
|
</p><h4>Contact us</h4>
|
|
|
|
<p class="topless"><a href="mailto:mps-questions@ravenbrook.com">mps-questions@ravenbrook.com</a></p>
|
|
</div>
|
|
</div>
|
|
<div class="clearer"></div>
|
|
</div>
|
|
<div class="related">
|
|
<h3>Navigation</h3>
|
|
<ul>
|
|
<li class="right" style="margin-right: 10px">
|
|
<a href="../genindex.html" title="General Index"
|
|
>index</a></li>
|
|
<li class="right" >
|
|
<a href="perf.html" title="5. Tuning the Memory Pool System for performance"
|
|
>next</a> |</li>
|
|
<li class="right" >
|
|
<a href="lang.html" title="3. Garbage collecting a language with the Memory Pool System"
|
|
>previous</a> |</li>
|
|
<li><a href="../index.html">Memory Pool System 1.111.0 documentation</a> »</li>
|
|
<li><a href="index.html" >Guide</a> »</li>
|
|
</ul>
|
|
</div>
|
|
<div class="footer">
|
|
© <a href="../copyright.html">Copyright</a> 2013, Ravenbrook Limited.
|
|
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.
|
|
</div>
|
|
</body>
|
|
</html> |