Is Phobos's Garbage Collector utterly broken? (Phobos vs Tango)

Jascha Wetzel firstname at mainia.de
Mon Sep 17 06:30:01 PDT 2007


Sean Kelly wrote:
> Jascha Wetzel wrote:
>> Vladimir Panteleev wrote:
>>> On Wed, 01 Aug 2007 09:08:16 +0300, Vladimir Panteleev 
>>> <thecybershadow at gmail.com> wrote:
>>>
>>>> I initially wrote it to try to find a memory leak in Tango's GC 
>>>> (which was actually fixed at some point).
>>>
>>> Turns out it's still there, and it's the old "binary data" issue with 
>>> pointer-searching GCs, which was fixed in D/Phobos 1.001 by making 
>>> the GC type-aware. Check out the attached sample programs for a 
>>> simple example - the Tango version can't know there are no pointers 
>>> in its GrowBuffer's data, and thus leaks like crazy, while the Phobos 
>>> version stays at 13MB.
>>
>> i ran into another issue with the phobos gc. i have constant array 
>> literals that are used in a constructor to initialize a member. the 
>> data isn't always used. each instance uses it at most once. the second 
>> time an instance uses that data, it has been overwritten. the problem 
>> disappears if i disable the gc.
>> it looks like the gc frees the memory that holds the constant 
>> initializer. unfortunately it's really hard to reproduce this problem 
>> in a small program.
> 
> Have you tested this with Tango?  I would expect the same broken 
> behavior but you never know, and any differences may help track down the 
> issue.

Tango has the same problem. I couldn't find a small test program that 
provokes this problem, but i can reproduce it with a larger one.

The problem doesn't arise the second time it is used, as i guessed 
earlier, it's after the GC ran once. It seems to miss the root in B.data 
(see below), free that memory and re-assign it to some other block. When 
the program crashes, the memory pointed to by B.data has been 
overwritten with values (used as indeces) that cause the crash.
It's basically this:

align(1) struct C
{
    uint a, b, c;
    uint[] s;
}

abstract class A
{
   C[] data; // gets initialized in subclass' c'tor - see below

   void foo()
   {
     bar(&data[calcIndex()]);
   }

   void bar(C* a)
   {
     foreach ( s; a.s )
       doSomething(s);  // crashes because s is used as an index
   }
}

class B : A
{
   this()
   {
     data = [
         C(1,2,3,[4,5,6]),
         C(7,8,9,[1,3,6]),
         C(35,5,88,[1234,78,6])
     ];
   }
}



More information about the Digitalmars-d mailing list