Austin Schuh | 745610d | 2015-09-06 18:19:50 -0700 | [diff] [blame] | 1 | <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> |
| 2 | <HTML> |
| 3 | |
| 4 | <HEAD> |
| 5 | <link rel="stylesheet" href="designstyle.css"> |
| 6 | <title>Gperftools Heap Leak Checker</title> |
| 7 | </HEAD> |
| 8 | |
| 9 | <BODY> |
| 10 | |
| 11 | <p align=right> |
| 12 | <i>Last modified |
| 13 | <script type=text/javascript> |
| 14 | var lm = new Date(document.lastModified); |
| 15 | document.write(lm.toDateString()); |
| 16 | </script></i> |
| 17 | </p> |
| 18 | |
| 19 | <p>This is the heap checker we use at Google to detect memory leaks in |
| 20 | C++ programs. There are three parts to using it: linking the library |
| 21 | into an application, running the code, and analyzing the output.</p> |
| 22 | |
| 23 | |
| 24 | <H1>Linking in the Library</H1> |
| 25 | |
| 26 | <p>The heap-checker is part of tcmalloc, so to install the heap |
| 27 | checker into your executable, add <code>-ltcmalloc</code> to the |
| 28 | link-time step for your executable. Also, while we don't necessarily |
| 29 | recommend this form of usage, it's possible to add in the profiler at |
| 30 | run-time using <code>LD_PRELOAD</code>:</p> |
| 31 | <pre>% env LD_PRELOAD="/usr/lib/libtcmalloc.so" <binary></pre> |
| 32 | |
| 33 | <p>This does <i>not</i> turn on heap checking; it just inserts the |
| 34 | code. For that reason, it's practical to just always link |
| 35 | <code>-ltcmalloc</code> into a binary while developing; that's what we |
| 36 | do at Google. (However, since any user can turn on the profiler by |
| 37 | setting an environment variable, it's not necessarily recommended to |
| 38 | install heapchecker-linked binaries into a production, running |
| 39 | system.) Note that if you wish to use the heap checker, you must |
| 40 | also use the tcmalloc memory-allocation library. There is no way |
| 41 | currently to use the heap checker separate from tcmalloc.</p> |
| 42 | |
| 43 | |
| 44 | <h1>Running the Code</h1> |
| 45 | |
| 46 | <p>Note: For security reasons, heap profiling will not write to a file |
| 47 | -- and is thus not usable -- for setuid programs.</p> |
| 48 | |
| 49 | <h2><a name="whole_program">Whole-program Heap Leak Checking</a></h2> |
| 50 | |
| 51 | <p>The recommended way to use the heap checker is in "whole program" |
| 52 | mode. In this case, the heap-checker starts tracking memory |
| 53 | allocations before the start of <code>main()</code>, and checks again |
| 54 | at program-exit. If it finds any memory leaks -- that is, any memory |
| 55 | not pointed to by objects that are still "live" at program-exit -- it |
| 56 | aborts the program (via <code>exit(1)</code>) and prints a message |
| 57 | describing how to track down the memory leak (using <A |
| 58 | HREF="heapprofile.html#pprof">pprof</A>).</p> |
| 59 | |
| 60 | <p>The heap-checker records the stack trace for each allocation while |
| 61 | it is active. This causes a significant increase in memory usage, in |
| 62 | addition to slowing your program down.</p> |
| 63 | |
| 64 | <p>Here's how to run a program with whole-program heap checking:</p> |
| 65 | |
| 66 | <ol> |
| 67 | <li> <p>Define the environment variable HEAPCHECK to the <A |
| 68 | HREF="#types">type of heap-checking</A> to do. For instance, |
| 69 | to heap-check |
| 70 | <code>/usr/local/bin/my_binary_compiled_with_tcmalloc</code>:</p> |
| 71 | <pre>% env HEAPCHECK=normal /usr/local/bin/my_binary_compiled_with_tcmalloc</pre> |
| 72 | </ol> |
| 73 | |
| 74 | <p>No other action is required.</p> |
| 75 | |
| 76 | <p>Note that since the heap-checker uses the heap-profiling framework |
| 77 | internally, it is not possible to run both the heap-checker and <A |
| 78 | HREF="heapprofile.html">heap profiler</A> at the same time.</p> |
| 79 | |
| 80 | |
| 81 | <h3><a name="types">Flavors of Heap Checking</a></h3> |
| 82 | |
| 83 | <p>These are the legal values when running a whole-program heap |
| 84 | check:</p> |
| 85 | <ol> |
| 86 | <li> <code>minimal</code> |
| 87 | <li> <code>normal</code> |
| 88 | <li> <code>strict</code> |
| 89 | <li> <code>draconian</code> |
| 90 | </ol> |
| 91 | |
| 92 | <p>"Minimal" heap-checking starts as late as possible in a |
| 93 | initialization, meaning you can leak some memory in your |
| 94 | initialization routines (that run before <code>main()</code>, say), |
| 95 | and not trigger a leak message. If you frequently (and purposefully) |
| 96 | leak data in one-time global initializers, "minimal" mode is useful |
| 97 | for you. Otherwise, you should avoid it for stricter modes.</p> |
| 98 | |
| 99 | <p>"Normal" heap-checking tracks <A HREF="#live">live objects</A> and |
| 100 | reports a leak for any data that is not reachable via a live object |
| 101 | when the program exits.</p> |
| 102 | |
| 103 | <p>"Strict" heap-checking is much like "normal" but has a few extra |
| 104 | checks that memory isn't lost in global destructors. In particular, |
| 105 | if you have a global variable that allocates memory during program |
| 106 | execution, and then "forgets" about the memory in the global |
| 107 | destructor (say, by setting the pointer to it to NULL) without freeing |
| 108 | it, that will prompt a leak message in "strict" mode, though not in |
| 109 | "normal" mode.</p> |
| 110 | |
| 111 | <p>"Draconian" heap-checking is appropriate for those who like to be |
| 112 | very precise about their memory management, and want the heap-checker |
| 113 | to help them enforce it. In "draconian" mode, the heap-checker does |
| 114 | not do "live object" checking at all, so it reports a leak unless |
| 115 | <i>all</i> allocated memory is freed before program exit. (However, |
| 116 | you can use <A HREF="#disable">IgnoreObject()</A> to re-enable |
| 117 | liveness-checking on an object-by-object basis.)</p> |
| 118 | |
| 119 | <p>"Normal" mode, as the name implies, is the one used most often at |
| 120 | Google. It's appropriate for everyday heap-checking use.</p> |
| 121 | |
| 122 | <p>In addition, there are two other possible modes:</p> |
| 123 | <ul> |
| 124 | <li> <code>as-is</code> |
| 125 | <li> <code>local</code> |
| 126 | </ul> |
| 127 | <p><code>as-is</code> is the most flexible mode; it allows you to |
| 128 | specify the various <A HREF="#options">knobs</A> of the heap checker |
| 129 | explicitly. <code>local</code> activates the <A |
| 130 | HREF="#explicit">explicit heap-check instrumentation</A>, but does not |
| 131 | turn on any whole-program leak checking.</p> |
| 132 | |
| 133 | |
| 134 | <h3><A NAME="tweaking">Tweaking whole-program checking</A></h3> |
| 135 | |
| 136 | <p>In some cases you want to check the whole program for memory leaks, |
| 137 | but waiting for after <code>main()</code> exits to do the first |
| 138 | whole-program leak check is waiting too long: e.g. in a long-running |
| 139 | server one might wish to simply periodically check for leaks while the |
| 140 | server is running. In this case, you can call the static method |
| 141 | <code>NoGlobalLeaks()</code>, to verify no global leaks have happened |
| 142 | as of that point in the program.</p> |
| 143 | |
| 144 | <p>Alternately, doing the check after <code>main()</code> exits might |
| 145 | be too late. Perhaps you have some objects that are known not to |
| 146 | clean up properly at exit. You'd like to do the "at exit" check |
| 147 | before those objects are destroyed (since while they're live, any |
| 148 | memory they point to will not be considered a leak). In that case, |
| 149 | you can call <code>NoGlobalLeaks()</code> manually, near the end of |
| 150 | <code>main()</code>, and then call <code>CancelGlobalCheck()</code> to |
| 151 | turn off the automatic post-<code>main()</code> check.</p> |
| 152 | |
| 153 | <p>Finally, there's a helper macro for "strict" and "draconian" modes, |
| 154 | which require all global memory to be freed before program exit. This |
| 155 | freeing can be time-consuming and is often unnecessary, since libc |
| 156 | cleans up all memory at program-exit for you. If you want the |
| 157 | benefits of "strict"/"draconian" modes without the cost of all that |
| 158 | freeing, look at <code>REGISTER_HEAPCHECK_CLEANUP</code> (in |
| 159 | <code>heap-checker.h</code>). This macro allows you to mark specific |
| 160 | cleanup code as active only when the heap-checker is turned on.</p> |
| 161 | |
| 162 | |
| 163 | <h2><a name="explicit">Explicit (Partial-program) Heap Leak Checking</h2> |
| 164 | |
| 165 | <p>Instead of whole-program checking, you can check certain parts of your |
| 166 | code to verify they do not have memory leaks. This check verifies that |
| 167 | between two parts of a program, no memory is allocated without being freed.</p> |
| 168 | <p>To use this kind of checking code, bracket the code you want |
| 169 | checked by creating a <code>HeapLeakChecker</code> object at the |
| 170 | beginning of the code segment, and call |
| 171 | <code>NoLeaks()</code> at the end. These functions, and all others |
| 172 | referred to in this file, are declared in |
| 173 | <code><gperftools/heap-checker.h></code>. |
| 174 | </p> |
| 175 | |
| 176 | <p>Here's an example:</p> |
| 177 | <pre> |
| 178 | HeapLeakChecker heap_checker("test_foo"); |
| 179 | { |
| 180 | code that exercises some foo functionality; |
| 181 | this code should not leak memory; |
| 182 | } |
| 183 | if (!heap_checker.NoLeaks()) assert(NULL == "heap memory leak"); |
| 184 | </pre> |
| 185 | |
| 186 | <p>Note that adding in the <code>HeapLeakChecker</code> object merely |
| 187 | instruments the code for leak-checking. To actually turn on this |
| 188 | leak-checking on a particular run of the executable, you must still |
| 189 | run with the heap-checker turned on:</p> |
| 190 | <pre>% env HEAPCHECK=local /usr/local/bin/my_binary_compiled_with_tcmalloc</pre> |
| 191 | <p>If you want to do whole-program leak checking in addition to this |
| 192 | manual leak checking, you can run in <code>normal</code> or some other |
| 193 | mode instead: they'll run the "local" checks in addition to the |
| 194 | whole-program check.</p> |
| 195 | |
| 196 | |
| 197 | <h2><a name="disable">Disabling Heap-checking of Known Leaks</a></h2> |
| 198 | |
| 199 | <p>Sometimes your code has leaks that you know about and are willing |
| 200 | to accept. You would like the heap checker to ignore them when |
| 201 | checking your program. You can do this by bracketing the code in |
| 202 | question with an appropriate heap-checking construct:</p> |
| 203 | <pre> |
| 204 | ... |
| 205 | { |
| 206 | HeapLeakChecker::Disabler disabler; |
| 207 | <leaky code> |
| 208 | } |
| 209 | ... |
| 210 | </pre> |
| 211 | Any objects allocated by <code>leaky code</code> (including inside any |
| 212 | routines called by <code>leaky code</code>) and any objects reachable |
| 213 | from such objects are not reported as leaks. |
| 214 | |
| 215 | <p>Alternately, you can use <code>IgnoreObject()</code>, which takes a |
| 216 | pointer to an object to ignore. That memory, and everything reachable |
| 217 | from it (by following pointers), is ignored for the purposes of leak |
| 218 | checking. You can call <code>UnIgnoreObject()</code> to undo the |
| 219 | effects of <code>IgnoreObject()</code>.</p> |
| 220 | |
| 221 | |
| 222 | <h2><a name="options">Tuning the Heap Checker</h2> |
| 223 | |
| 224 | <p>The heap leak checker has many options, some that trade off running |
| 225 | time and accuracy, and others that increase the sensitivity at the |
| 226 | risk of returning false positives. For most uses, the range covered |
| 227 | by the <A HREF="#types">heap-check flavors</A> is enough, but in |
| 228 | specialized cases more control can be helpful.</p> |
| 229 | |
| 230 | <p> |
| 231 | These options are specified via environment varaiables. |
| 232 | </p> |
| 233 | |
| 234 | <p>This first set of options controls sensitivity and accuracy. These |
| 235 | options are ignored unless you run the heap checker in <A |
| 236 | HREF="#types">as-is</A> mode. |
| 237 | |
| 238 | <table frame=box rules=sides cellpadding=5 width=100%> |
| 239 | |
| 240 | <tr valign=top> |
| 241 | <td><code>HEAP_CHECK_AFTER_DESTRUCTORS</code></td> |
| 242 | <td>Default: false</td> |
| 243 | <td> |
| 244 | When true, do the final leak check after all other global |
| 245 | destructors have run. When false, do it after all |
| 246 | <code>REGISTER_HEAPCHECK_CLEANUP</code>, typically much earlier in |
| 247 | the global-destructor process. |
| 248 | </td> |
| 249 | </tr> |
| 250 | |
| 251 | <tr valign=top> |
| 252 | <td><code>HEAP_CHECK_IGNORE_THREAD_LIVE</code></td> |
| 253 | <td>Default: true</td> |
| 254 | <td> |
| 255 | If true, ignore objects reachable from thread stacks and registers |
| 256 | (that is, do not report them as leaks). |
| 257 | </td> |
| 258 | </tr> |
| 259 | |
| 260 | <tr valign=top> |
| 261 | <td><code>HEAP_CHECK_IGNORE_GLOBAL_LIVE</code></td> |
| 262 | <td>Default: true</td> |
| 263 | <td> |
| 264 | If true, ignore objects reachable from global variables and data |
| 265 | (that is, do not report them as leaks). |
| 266 | </td> |
| 267 | </tr> |
| 268 | |
| 269 | </table> |
| 270 | |
| 271 | <p>These options modify the behavior of whole-program leak |
| 272 | checking.</p> |
| 273 | |
| 274 | <table frame=box rules=sides cellpadding=5 width=100%> |
| 275 | |
| 276 | <tr valign=top> |
| 277 | <td><code>HEAP_CHECK_MAX_LEAKS</code></td> |
| 278 | <td>Default: 20</td> |
| 279 | <td> |
| 280 | The maximum number of leaks to be printed to stderr (all leaks are still |
| 281 | emitted to file output for pprof to visualize). If negative or zero, |
| 282 | print all the leaks found. |
| 283 | </td> |
| 284 | </tr> |
| 285 | |
| 286 | |
| 287 | </table> |
| 288 | |
| 289 | <p>These options apply to all types of leak checking.</p> |
| 290 | |
| 291 | <table frame=box rules=sides cellpadding=5 width=100%> |
| 292 | |
| 293 | <tr valign=top> |
| 294 | <td><code>HEAP_CHECK_IDENTIFY_LEAKS</code></td> |
| 295 | <td>Default: false</td> |
| 296 | <td> |
| 297 | If true, generate the addresses of the leaked objects in the |
| 298 | generated memory leak profile files. |
| 299 | </td> |
| 300 | </tr> |
| 301 | |
| 302 | <tr valign=top> |
| 303 | <td><code>HEAP_CHECK_TEST_POINTER_ALIGNMENT</code></td> |
| 304 | <td>Default: false</td> |
| 305 | <td> |
| 306 | If true, check all leaks to see if they might be due to the use |
| 307 | of unaligned pointers. |
| 308 | </td> |
| 309 | </tr> |
| 310 | |
| 311 | <tr valign=top> |
| 312 | <td><code>HEAP_CHECK_POINTER_SOURCE_ALIGNMENT</code></td> |
| 313 | <td>Default: sizeof(void*)</td> |
| 314 | <td> |
| 315 | Alignment at which all pointers in memory are supposed to be located. |
| 316 | Use 1 if any alignment is ok. |
| 317 | </td> |
| 318 | </tr> |
| 319 | |
| 320 | <tr valign=top> |
| 321 | <td><code>PPROF_PATH</code></td> |
| 322 | <td>Default: pprof</td> |
| 323 | <td> |
| 324 | The location of the <code>pprof</code> executable. |
| 325 | </td> |
| 326 | </tr> |
| 327 | |
| 328 | <tr valign=top> |
| 329 | <td><code>HEAP_CHECK_DUMP_DIRECTORY</code></td> |
| 330 | <td>Default: /tmp</td> |
| 331 | <td> |
| 332 | Where the heap-profile files are kept while the program is running. |
| 333 | </td> |
| 334 | </tr> |
| 335 | |
| 336 | </table> |
| 337 | |
| 338 | |
| 339 | <h2>Tips for Handling Detected Leaks</h2> |
| 340 | |
| 341 | <p>What do you do when the heap leak checker detects a memory leak? |
| 342 | First, you should run the reported <code>pprof</code> command; |
| 343 | hopefully, that is enough to track down the location where the leak |
| 344 | occurs.</p> |
| 345 | |
| 346 | <p>If the leak is a real leak, you should fix it!</p> |
| 347 | |
| 348 | <p>If you are sure that the reported leaks are not dangerous and there |
| 349 | is no good way to fix them, then you can use |
| 350 | <code>HeapLeakChecker::Disabler</code> and/or |
| 351 | <code>HeapLeakChecker::IgnoreObject()</code> to disable heap-checking |
| 352 | for certain parts of the codebase.</p> |
| 353 | |
| 354 | <p>In "strict" or "draconian" mode, leaks may be due to incomplete |
| 355 | cleanup in the destructors of global variables. If you don't wish to |
| 356 | augment the cleanup routines, but still want to run in "strict" or |
| 357 | "draconian" mode, consider using <A |
| 358 | HREF="#tweaking"><code>REGISTER_HEAPCHECK_CLEANUP</code></A>.</p> |
| 359 | |
| 360 | <h2>Hints for Debugging Detected Leaks</h2> |
| 361 | |
| 362 | <p>Sometimes it can be useful to not only know the exact code that |
| 363 | allocates the leaked objects, but also the addresses of the leaked objects. |
| 364 | Combining this e.g. with additional logging in the program |
| 365 | one can then track which subset of the allocations |
| 366 | made at a certain spot in the code are leaked. |
| 367 | <br/> |
| 368 | To get the addresses of all leaked objects |
| 369 | define the environment variable <code>HEAP_CHECK_IDENTIFY_LEAKS</code> |
| 370 | to be <code>1</code>. |
| 371 | The object addresses will be reported in the form of addresses |
| 372 | of fake immediate callers of the memory allocation routines. |
| 373 | Note that the performance of doing leak-checking in this mode |
| 374 | can be noticeably worse than the default mode. |
| 375 | </p> |
| 376 | |
| 377 | <p>One relatively common class of leaks that don't look real |
| 378 | is the case of multiple initialization. |
| 379 | In such cases the reported leaks are typically things that are |
| 380 | linked from some global objects, |
| 381 | which are initialized and say never modified again. |
| 382 | The non-obvious cause of the leak is frequently the fact that |
| 383 | the initialization code for these objects executes more than once. |
| 384 | <br/> |
| 385 | E.g. if the code of some <code>.cc</code> file is made to be included twice |
| 386 | into the binary, then the constructors for global objects defined in that file |
| 387 | will execute twice thus leaking the things allocated on the first run. |
| 388 | <br/> |
| 389 | Similar problems can occur if object initialization is done more explicitly |
| 390 | e.g. on demand by a slightly buggy code |
| 391 | that does not always ensure only-once initialization. |
| 392 | </p> |
| 393 | |
| 394 | <p> |
| 395 | A more rare but even more puzzling problem can be use of not properly |
| 396 | aligned pointers (maybe inside of not properly aligned objects). |
| 397 | Normally such pointers are not followed by the leak checker, |
| 398 | hence the objects reachable only via such pointers are reported as leaks. |
| 399 | If you suspect this case |
| 400 | define the environment variable <code>HEAP_CHECK_TEST_POINTER_ALIGNMENT</code> |
| 401 | to be <code>1</code> |
| 402 | and then look closely at the generated leak report messages. |
| 403 | </p> |
| 404 | |
| 405 | <h1>How It Works</h1> |
| 406 | |
| 407 | <p>When a <code>HeapLeakChecker</code> object is constructed, it dumps |
| 408 | a memory-usage profile named |
| 409 | <code><prefix>.<name>-beg.heap</code> to a temporary |
| 410 | directory. When <code>NoLeaks()</code> |
| 411 | is called (for whole-program checking, this happens automatically at |
| 412 | program-exit), it dumps another profile, named |
| 413 | <code><prefix>.<name>-end.heap</code>. |
| 414 | (<code><prefix></code> is typically determined automatically, |
| 415 | and <code><name></code> is typically <code>argv[0]</code>.) It |
| 416 | then compares the two profiles. If the second profile shows |
| 417 | more memory use than the first, the |
| 418 | <code>NoLeaks()</code> function will |
| 419 | return false. For "whole program" profiling, this will cause the |
| 420 | executable to abort (via <code>exit(1)</code>). In all cases, it will |
| 421 | print a message on how to process the dumped profiles to locate |
| 422 | leaks.</p> |
| 423 | |
| 424 | <h3><A name=live>Detecting Live Objects</A></h3> |
| 425 | |
| 426 | <p>At any point during a program's execution, all memory that is |
| 427 | accessible at that time is considered "live." This includes global |
| 428 | variables, and also any memory that is reachable by following pointers |
| 429 | from a global variable. It also includes all memory reachable from |
| 430 | the current stack frame and from current CPU registers (this captures |
| 431 | local variables). Finally, it includes the thread equivalents of |
| 432 | these: thread-local storage and thread heaps, memory reachable from |
| 433 | thread-local storage and thread heaps, and memory reachable from |
| 434 | thread CPU registers.</p> |
| 435 | |
| 436 | <p>In all modes except "draconian," live memory is not |
| 437 | considered to be a leak. We detect this by doing a liveness flood, |
| 438 | traversing pointers to heap objects starting from some initial memory |
| 439 | regions we know to potentially contain live pointer data. Note that |
| 440 | this flood might potentially not find some (global) live data region |
| 441 | to start the flood from. If you find such, please file a bug.</p> |
| 442 | |
| 443 | <p>The liveness flood attempts to treat any properly aligned byte |
| 444 | sequences as pointers to heap objects and thinks that it found a good |
| 445 | pointer whenever the current heap memory map contains an object with |
| 446 | the address whose byte representation we found. Some pointers into |
| 447 | not-at-start of object will also work here.</p> |
| 448 | |
| 449 | <p>As a result of this simple approach, it's possible (though |
| 450 | unlikely) for the flood to be inexact and occasionally result in |
| 451 | leaked objects being erroneously determined to be live. For instance, |
| 452 | random bit patterns can happen to look like pointers to leaked heap |
| 453 | objects. More likely, stale pointer data not corresponding to any |
| 454 | live program variables can be still present in memory regions, |
| 455 | especially in thread stacks. For instance, depending on how the local |
| 456 | <code>malloc</code> is implemented, it may reuse a heap object |
| 457 | address:</p> |
| 458 | <pre> |
| 459 | char* p = new char[1]; // new might return 0x80000000, say. |
| 460 | delete p; |
| 461 | new char[1]; // new might return 0x80000000 again |
| 462 | // This last new is a leak, but doesn't seem it: p looks like it points to it |
| 463 | </pre> |
| 464 | |
| 465 | <p>In other words, imprecisions in the liveness flood mean that for |
| 466 | any heap leak check we might miss some memory leaks. This means that |
| 467 | for local leak checks, we might report a memory leak in the local |
| 468 | area, even though the leak actually happened before the |
| 469 | <code>HeapLeakChecker</code> object was constructed. Note that for |
| 470 | whole-program checks, a leak report <i>does</i> always correspond to a |
| 471 | real leak (since there's no "before" to have created a false-live |
| 472 | object).</p> |
| 473 | |
| 474 | <p>While this liveness flood approach is not very portable and not |
| 475 | 100% accurate, it works in most cases and saves us from writing a lot |
| 476 | of explicit clean up code and other hassles when dealing with thread |
| 477 | data.</p> |
| 478 | |
| 479 | |
| 480 | <h3>Visualizing Leak with <code>pprof</code></h3> |
| 481 | |
| 482 | <p> |
| 483 | The heap checker automatically prints basic leak info with stack traces of |
| 484 | leaked objects' allocation sites, as well as a pprof command line that can be |
| 485 | used to visualize the call-graph involved in these allocations. |
| 486 | The latter can be much more useful for a human |
| 487 | to see where/why the leaks happened, especially if the leaks are numerous. |
| 488 | </p> |
| 489 | |
| 490 | <h3>Leak-checking and Threads</h3> |
| 491 | |
| 492 | <p>At the time of HeapLeakChecker's construction and during |
| 493 | <code>NoLeaks()</code> calls, we grab a lock |
| 494 | and then pause all other threads so other threads do not interfere |
| 495 | with recording or analyzing the state of the heap.</p> |
| 496 | |
| 497 | <p>In general, leak checking works correctly in the presence of |
| 498 | threads. However, thread stack data liveness determination (via |
| 499 | <code>base/thread_lister.h</code>) does not work when the program is |
| 500 | running under GDB, because the ptrace functionality needed for finding |
| 501 | threads is already hooked to by GDB. Conversely, leak checker's |
| 502 | ptrace attempts might also interfere with GDB. As a result, GDB can |
| 503 | result in potentially false leak reports. For this reason, the |
| 504 | heap-checker turns itself off when running under GDB.</p> |
| 505 | |
| 506 | <p>Also, <code>thread_lister</code> only works for Linux pthreads; |
| 507 | leak checking is unlikely to handle other thread implementations |
| 508 | correctly.</p> |
| 509 | |
| 510 | <p>As mentioned in the discussion of liveness flooding, thread-stack |
| 511 | liveness determination might mis-classify as reachable objects that |
| 512 | very recently became unreachable (leaked). This can happen when the |
| 513 | pointers to now-logically-unreachable objects are present in the |
| 514 | active thread stack frame. In other words, trivial code like the |
| 515 | following might not produce the expected leak checking outcome |
| 516 | depending on how the compiled code works with the stack:</p> |
| 517 | <pre> |
| 518 | int* foo = new int [20]; |
| 519 | HeapLeakChecker check("a_check"); |
| 520 | foo = NULL; |
| 521 | // May fail to trigger. |
| 522 | if (!heap_checker.NoLeaks()) assert(NULL == "heap memory leak"); |
| 523 | </pre> |
| 524 | |
| 525 | |
| 526 | <hr> |
| 527 | <address>Maxim Lifantsev<br> |
| 528 | <!-- Created: Tue Dec 19 10:43:14 PST 2000 --> |
| 529 | <!-- hhmts start --> |
| 530 | Last modified: Fri Jul 13 13:14:33 PDT 2007 |
| 531 | <!-- hhmts end --> |
| 532 | </address> |
| 533 | </body> |
| 534 | </html> |