A few considerations on garbage collection

Andrei Alexandrescu via Digitalmars-d digitalmars-d at puremagic.com
Wed Apr 30 08:33:25 PDT 2014


I'm mulling over a couple of design considerations for allocators, and 
was thinking of the following restriction:

1. No out-of-bounds tricks and no pointer arithmetic. Consider:

int[] a = new int[1000];
a = a[250 .. 750];
int* p = a[500 .. $].ptr;

Subsequently the GC should be within its rights to deallocate any memory 
within the first and last 250 integers allocated, even though in theory 
the user may get to them by using pointer arithmetic.

In particular that means once a slice is shrunk, there's no growing back 
unless another slice is around.

I think the current GC already does that.

2. The same may be the case for classes WITHOUT destructors. Consider:

class A
{
    int[1000] a;
    int b;
    int[1000] c;
}
int* p = &(new A).b;

The collector should be allowed to deallocate any memory except b's own, 
even though that means the class has "holes" in it. The current GC does 
not do that.

2. However, the same shall not be the case for classes with destructors. 
Consider:

class B
{
    int[1000] a;
    int b;
    int[1000] c;
    ~this() { ... }
}
int* p = &(new B).b;

This class has a destructor, so it will be kept around in its entirety 
if an internal pointer is held.

3. Classes meant to have destructors called at collection will ALWAYS 
have been allocated with new (i.e. won't start in the middle of some 
other allocation). In other words, only class objects created with new 
will be properly collected. Those forced in odd places with emplace() 
are the responsibility of the user.

4. Currently, struct objects created with new do NOT have their 
destructors called during collection. I think this may continue, meaning 
that structs created with new are somewhat low-level and are meant to be 
destroyed and deallocated manually.

5. This brings up arrays of structs. As far as I understand, destructors 
will never be called for these, even after all references are gone:

struct S { ~this() { ... } }
auto a = new S[100];

Unlike (4), arrays of structs are high-level and frequently used. I 
think we must do something about it, so I plan to support calling 
destructors for arrays of structs.

6. The point above brings to mind more radical possibilities, such as 
making all arrays reference-counted and allowing compulsive deallocation 
when the reference counter goes down to zero. That would rule out things 
like escaping pointers to data inside arrays, which is quite extreme. 
But probably worth bringing up in a brainstorming. If we disallow 
statically constructs that take addresses we may get away with it.

Please chime in with your thoughts.

Andrei


More information about the Digitalmars-d mailing list