Mail Archives: djgpp/2000/01/24/14:16:38
I was wondering if anyone could help me find
a mysterious problem in gcc 2.95.2:
Page fault at eip=0017651f, error=0004
eax=00e45840 ebx=00392604 ecx=00392604 edx=00fd53330 esi=003935fc
edi=00391610
ebp=003303b0 esp=003303a4 program=C:\DJGPP\BIN\CC1.EXE
cs: sel=00a7 base=81043000 limit=fffeffff
ds: sel=00af base=81043000 limit=fffeffff
es: sel=00af base=81043000 limit=fffeffff
fs: sel=0087 base=0001e3e0 limit=0000ffff
gs: sel=00bf base=00000000 limit=0010ffff
ss: sel=00af base=81043000 limit=fffeffff
App stack: [00332000..001b2000] Exceptn stack: [001a2818..001a08d8]
Call frame traceback EIPs:
0x0017651f 0x17651f _free+0x77
0x00174474 0x174474
0x000dc172 0xdc172
0x000ce040 0xce040
0x0000b182 0xb182
0x001627fc 0x1627fc
0x0014edf2 0x14edf2
0x00009b41 0x9b41
0x0000d9cf 0xd9cf
0x0017589a 0x17589a
I used objdump on cc1.exe and found that the
failing address is _free+0x77. It seems to be in
the first call to the "merge" function, and it
happens when a for-loop is initialized:
for (bp=freelist[bu]; bp; bpp=&(bp->next), bp=bp->next) <---page fault
bp=freelist[bu] gives page fault because "bu"
has a very high value (bu=edi=0x00391610).
bu comes from b2bucket, so I think something
goes wrong there.
The error seems to be data-dependent, it doesn't
show up everytime, only when I run a special
sequence of programs, and only in a Win3.11 DOS box.
With plain DOS, everything works fine.
Now, I have a work-around for this problem and
that is to disable Virtual Memory either in Windows
or with _CRT0_FLAG_LOCK_MEMORY in gcc.
Then everything works fine again.
Thanks in advance for any ideas
--
Erik Berglund
erik2 DOT berglund AT telia DOT com
From malloc.c (version 2.02):
static inline int
size2bucket(unsigned size)
{
int rv=0;
size>>=2;
while (size)
{
rv++;
size>>=1;
}
return rv;
}
static inline int
b2bucket(BLOCK *b)
{
if (b->bucket == -1)
b->bucket = size2bucket(b->size);
return b->bucket;
}
static inline BLOCK *
merge(BLOCK *a, BLOCK *b, BLOCK *c)
{
int bu;
BLOCK *bp, **bpp;
#if DEBUG
printf(" merge %d/%08x + %d/%08x = %d\n",
a->size, a, b->size, b, a->size+b->size+8);
#endif
CHECK(a);
CHECK(b);
CHECK(c);
if (c == slop)
{
#if DEBUG
printf(" snipping slop %d/%08x\n", slop->size, slop);
#endif
slop = 0;
}
bu = b2bucket(c);
#if DEBUG
printf("bucket for %d/%08x is %d\n", c->size, c, bu);
#endif
bpp = freelist+bu;
for (bp=freelist[bu]; bp; bpp=&(bp->next), bp=bp->next) <---page fault
{
#if DEBUG
printf(" %08x", bp);
#endif
if (bp == c)
{
#if DEBUG
printf("\n snipping %d/%08x from freelist[%d]\n", bp->size, bp, bu);
#endif
*bpp = bp->next;
break;
}
}
CHECK(c);
a->size += b->size + 8;
a->bucket = -1;
ENDSZ(a) = a->size;
CHECK(a);
return a;
}
void
free(void *ptr)
{
int b;
BLOCK *block;
if (ptr == 0)
return;
block = (BLOCK *)((char *)ptr-4);
#if NUMSMALL
if (block->size < SMALL)
{
block->next = smallblocks[block->size/ALIGN];
smallblocks[block->size/ALIGN] = block;
return;
}
#endif
block->size &= ~1;
ENDSZ(block) &= ~1;
block->bucket = -1;
#if DEBUG
printf("free(%d/%08x)\n", block->size, block);
#endif
CHECK(block);
if (! (AFTER(block)->size & 1))
{
CHECK(AFTER(block));
}
if (! (BEFSZ(block) & 1))
{
CHECK(BEFORE(block));
block = merge(BEFORE(block), block, BEFORE(block));
}
CHECK(block);
if (! (AFTER(block)->size & 1))
{
CHECK(AFTER(block));
block = merge(block, AFTER(block), AFTER(block));
}
CHECK(block);
b = b2bucket(block);
block->next = freelist[b];
freelist[b] = block;
CHECK(block);
}
- Raw text -