⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 debugging.html

📁 A garbage collector for C and C
💻 HTML
📖 第 1 页 / 共 2 页
字号:
<HTML><HEAD><TITLE>Debugging Garbage Collector Related Problems</title></head><BODY><H1>Debugging Garbage Collector Related Problems</h1>This page contains some hints ondebugging issues specific tothe Boehm-Demers-Weiser conservative garbage collector.It applies both to debugging issues in client code that manifest themselvesas collector misbehavior, and to debugging the collector itself.<P>If you suspect a bug in the collector itself, it is strongly recommendedthat you try the latest collector release, even if it is labelled as "alpha",before proceeding.<H2>Bus Errors and Segmentation Violations</h2><P>If the fault occurred in GC_find_limit, or with incremental collection enabled,this is probably normal.  The collector installs handlers to take care ofthese.  You will not see these unless you are using a debugger.Your debugger <I>should</i> allow you to continue.It's often preferable to tell the debugger to ignore SIGBUS and SIGSEGV("<TT>handle SIGSEGV SIGBUS nostop noprint</tt>" in gdb,"<TT>ignore SIGSEGV SIGBUS</tt>" in most versions of dbx)and set a breakpoint in <TT>abort</tt>.The collector will call abort if the signal had another cause,and there was not other handler previously installed.<P>We recommend debugging without incremental collection if possible.(This applies directly to UNIX systems.Debugging with incremental collection under win32 is worse.  See README.win32.)<P>If the application generates an unhandled SIGSEGV or equivalent, it mayoften be easiest to set the environment variable GC_LOOP_ON_ABORT.  On manyplatforms, this will cause the collector to loop in a handler when theSIGSEGV is encountered (or when the collector aborts for some other reason),and a debugger can then be attached to the loopingprocess.  This sidesteps common operating system problems relatedto incomplete core files for multithreaded applications, etc.<H2>Other Signals</h2>On most platforms, the multithreaded version of the collector needs one ortwo other signals for internal use by the collector in stopping threads.It is normally wise to tell the debugger to ignore these.  On Linux,the collector currently uses SIGPWR and SIGXCPU by default.<H2>Warning Messages About Needing to Allocate Blacklisted Blocks</h2>The garbage collector generates warning messages of the form<PRE>Needed to allocate blacklisted block at 0x...</pre>or<PRE>Repeated allocation of very large block ...</pre>when it needs to allocate a block at a location that it knows to bereferenced by a false pointer.  These false pointers can be either permanent(<I>e.g.</i> a static integer variable that never changes) or temporary.In the latter case, the warning is largely spurious, and the block willeventually be reclaimed normally.In the former case, the program will still run correctly, but the blockwill never be reclaimed.  Unless the block is intended to bepermanent, the warning indicates a memory leak.<OL><LI>Ignore these warnings while you are using GC_DEBUG.  Some of the routinesmentioned below don't have debugging equivalents.  (Alternatively, writethe missing routines and send them to me.)<LI>Replace allocator calls that request large blocks with calls to<TT>GC_malloc_ignore_off_page</tt> or<TT>GC_malloc_atomic_ignore_off_page</tt>.  You may want to set abreakpoint in <TT>GC_default_warn_proc</tt> to help you identify such calls.Make sure that a pointer to somewhere near the beginning of the resulting blockis maintained in a (preferably volatile) variable as long asthe block is needed.<LI>If the large blocks are allocated with realloc, we suggest instead allocatingthem with something like the following.  Note that the realloc size incrementshould be fairly large (e.g. a factor of 3/2) for this to exhibit reasonableperformance.  But we all know we should do that anyway.<PRE>void * big_realloc(void *p, size_t new_size){    size_t old_size = GC_size(p);    void * result;     if (new_size <= 10000) return(GC_realloc(p, new_size));    if (new_size <= old_size) return(p);    result = GC_malloc_ignore_off_page(new_size);    if (result == 0) return(0);    memcpy(result,p,old_size);    GC_free(p);    return(result);}</pre><LI> In the unlikely case that even relatively small object(&lt;20KB) allocations are triggering these warnings, then your addressspace contains lots of "bogus pointers", i.e. values that appear tobe pointers but aren't.  Usually this can be solved by using GC_malloc_atomicor the routines in gc_typed.h to allocate large pointer-free regions of bitmaps, etc.  Sometimes the problem can be solved with trivial changes of encodingin certain values.  It is possible, to identify the source of the boguspointers by building the collector with <TT>-DPRINT_BLACK_LIST</tt>,which will cause it to print the "bogus pointers", along with their location.<LI> If you get only a fixed number of these warnings, you are probably onlyintroducing a bounded leak by ignoring them.  If the data structures beingallocated are intended to be permanent, then it is also safe to ignore them.The warnings can be turned off by calling GC_set_warn_proc with a procedurethat ignores these warnings (e.g. by doing absolutely nothing).</ol><H2>The Collector References a Bad Address in <TT>GC_malloc</tt></h2>This typically happens while the collector is trying to remove an entry fromits free list, and the free list pointer is bad because the free list linkin the last allocated object was bad.<P>With &gt; 99% probability, you wrote past the end of an allocated object.Try setting <TT>GC_DEBUG</tt> before including <TT>gc.h</tt> andallocating with <TT>GC_MALLOC</tt>.  This will try to detect suchoverwrite errors.<H2>Unexpectedly Large Heap</h2>Unexpected heap growth can be due to one of the following:<OL><LI> Data structures that are being unintentionally retained.  Thisis commonly caused by data structures that are no longer being used,but were not cleared, or by caches growing without bounds.<LI> Pointer misidentification.  The garbage collector is interpretingintegers or other data as pointers and retaining the "referenced"objects.  A common symptom is that GC_dump() shows much of the heapas black-listed.<LI> Heap fragmentation.  This should never result in unbounded growth,but it may account for larger heaps.  This is most commonly causedby allocation of large objects.  On some platforms it can be reducedby building with -DUSE_MUNMAP, which will cause the collector to unmapmemory corresponding to pages that have not been recently used.<LI> Per object overhead.  This is usually a relatively minor effect, butit may be worth considering.  If the collector recognizes interiorpointers, object sizes are increased, so that one-past-the-end pointersare correctly recognized.  The collector can be configured not to do this(<TT>-DDONT_ADD_BYTE_AT_END</tt>).<P>The collector rounds up object sizes so the result fits well into thechunk size (<TT>HBLKSIZE</tt>, normally 4K on 32 bit machines, 8Kon 64 bit machines) used by the collector.   Thus it may be worth avoidingobjects of size 2K + 1 (or 2K if a byte is being added at the end.)</ol>The last two cases can often be identified by looking at the outputof a call to <TT>GC_dump()</tt>.  Among other things, it will print thelist of free heap blocks, and a very brief description of all chunks inthe heap, the object sizes they correspond to, and how many live objectswere found in the chunk at the last collection.<P>Growing data structures can usually be identified by

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -