Found? Re: [Gc] Assertion failure in GC_malloc_uncollectable: GC_ASSERT(hhdr -> hb_n_marks == 0)

Jan Wielemaker J.Wielemaker at
Mon May 14 05:34:59 PDT 2012


The thing below is still bothering me, but I think I tracked it down to
a wrong GC_ASSERT() in GC_malloc_uncollectable().  For large objects, we
have this code:

         op = (ptr_t)GC_generic_malloc((word)lb, UNCOLLECTABLE);
         if (0 == op) return(0);

         GC_ASSERT(((word)op & (HBLKSIZE - 1)) == 0); /* large block */
         hhdr = HDR(op);
         /* We don't need the lock here, since we have an undisguised    */
         /* pointer.  We do need to hold the lock while we adjust        */
         /* mark bits.                                                   */
         GC_ASSERT(hhdr -> hb_n_marks == 0);

Where the last GC_ASSERT triggers for me.  I consistently find that
hb_last_reclaimed is one less than GC_gc_no.  I added the same assertion
to GC_generic_malloc() before the GC lock was released.  In that case, 
it is still the assert above that triggers.  This can be explained:
GC_generic_malloc() releases the lock, a GC marks the object and the
assertion in GC_malloc_uncollectable() fails.  Right?

Now, I think that the assertion is simply wrong and there is no need
to change anything else to the code, but I would be grateful if someone
with in-depth knowledge can confirm this.

	Cheers --- Jan

P.s.	The crash happens consistently(?) while the block is allocated
	from the final for-loop in GC_allochblk() (i.e., allocating
	from a bigger free list and splitting.  This might suggest
	there is more to it that just removing the GC_ASSERT().

On 05/02/2012 11:36 AM, Jan Wielemaker wrote:
> Hi,
> I'm experiencing assertion failures with GC_malloc_uncollectable() on a
> big block (usually a few 100 Kb): GC_ASSERT(hhdr -> hb_n_marks == 0).
> Now, I have to admit this is on a modified version (as discussed on this
> list). The version is based on a1467f2140f9db3408f6214137c7dc31f10d0bd9
> (Jan 16 git version). Using the unmodified version would require many
> changes to the program :-(
> This is merely a quick investigation to see whether this rings a bell
> with someone. Platform is X64 Linux (Ubuntu). GC Config flags:
> '--enable-threads=pthreads' '--enable-parallel-mark'
> '--enable-large-config' '--enable-gc-assertions'
> hhdr is this:
> (gdb) p *hhdr
> $1 = {hb_next = 0x0, hb_prev = 0x0, hb_block = 0x23ba000,
> hb_obj_kind = 2 '\002', hb_flags = 0 '\000', hb_last_reclaimed = 7,
> hb_sz = 196624, hb_descr = 196624, hb_large_block = 1 '\001',
> hb_map = 0x638f60, hb_n_marks = 1, hb_n_uncollectable = 0,
> _mark_byte_union = {_hb_marks = "\001", '\000' <repeats 255 times>, "\001",
> dummy = 1}}
> Only one thread is doing work at the moment of the crash; several others
> block waiting on the allocation lock. As I read it, hhdr suggests that
> the block is marked and in use, so it shouldn't be handed out by a new
> allocation call, right?
> The program does lots of complicated stuff using the garbage collector,
> but the crash is always in the big GC_malloc_uncollectable() called from
> the same context. These allocations manage a big buffer that is resized
> (doubled) using a new GC_malloc_uncollectable(), copy the data and call
> GC_free() on the old data. Several threads play the same game, on their
> own private datastructures. Of course, this means that an old buffer
> released using GC_free() in one thread is typically a good candidate for
> another thread. The crash is not very frequent: I need to make the
> program go through the critical process several hundred times to get
> a crash.
> Thanks for any hint
> --- Jan
> _______________________________________________
> Gc mailing list
> Gc at

More information about the Gc mailing list