[gclist] Possbile compatibilty problem with B-W GC and Win2000
wink
wink@saville.com
Wed, 16 Jan 2002 20:14:27 -0800
Hello all,
I'd like to report a possible compatibility problem with the B-W GC
and Windows 2000. The problem occurs after a 256K block was coalesced
with a 1MB block in GC_freehblk and then when GC_remove_protection is
called the invocation of UNPROTECT causes an abort.
I was using gc_cpp and creating objects that were slightly larger
than 1mb with incremental mode enabled. The problem appears to be
that blocks allocated by VirtualAlloc can't have VirtualProtect
called when coalescing has occurred. A quick and dirty solution was
to change GC_freehblk as below, this causes GC_freehblk to never
coalesce blocks. This is probably not a good solution, but it appears
to work.
Who is current "maintaining" B-W GC for windows, I'd like to be sure
this information gets to them and hopefully we can create a proper
solution.
Thanks,
Wink Saville
/*
* Free a heap block.
*
* Coalesce the block with its neighbors if possible.
*
* All mark words are assumed to be cleared.
*/
void
GC_freehblk(hbp)
struct hblk *hbp;
{
struct hblk *next, *prev;
hdr *hhdr, *prevhdr, *nexthdr;
signed_word size;
GET_HDR(hbp, hhdr);
size = hhdr->hb_sz;
size = HBLKSIZE * OBJ_SZ_TO_BLOCKS(size);
GC_remove_counts(hbp, (word)size);
hhdr->hb_sz = size;
/* Check for duplicate deallocation in the easy case */
if (HBLK_IS_FREE(hhdr)) {
GC_printf1("Duplicate large block deallocation of 0x%lx\n",
(unsigned long) hbp);
ABORT("Duplicate large block deallocation");
}
GC_ASSERT(IS_MAPPED(hhdr));
GC_invalidate_map(hhdr);
next = (struct hblk *)((word)hbp + size);
GET_HDR(next, nexthdr);
#ifndef MSWIN32
prev = GC_free_block_ending_at(hbp);
/* Coalesce with successor, if possible */
if(0 != nexthdr && HBLK_IS_FREE(nexthdr) && IS_MAPPED(nexthdr))
{
GC_remove_from_fl(nexthdr, FL_UNKNOWN);
hhdr -> hb_sz += nexthdr -> hb_sz;
GC_remove_header(next);
}
/* Coalesce with predecessor, if possible. */
if (0 != prev) {
prevhdr = HDR(prev);
if (IS_MAPPED(prevhdr)) {
GC_remove_from_fl(prevhdr, FL_UNKNOWN);
prevhdr -> hb_sz += hhdr -> hb_sz;
GC_remove_header(hbp);
hbp = prev;
hhdr = prevhdr;
}
}
#endif
GC_large_free_bytes += size;
GC_add_to_fl(hbp, hhdr);
}