Destructor semantics

Steven Schveighoffer schveiguy at yahoo.com
Wed Aug 11 06:03:53 PDT 2010


On Wed, 11 Aug 2010 03:12:57 -0400, foobar <foo at bar.com> wrote:

> Rainer Deyke Wrote:
>
>> On 8/10/2010 16:59, foobar wrote:
>> > Steven Schveighoffer Wrote:
>> >> what happens when GC destroys a C?
>> >>
>> >> C::~this(); // auto generated
>> >>   B::~this(); // so good so far
>> >>     A::~this(); // oops!  the a is gone, program vomits bits all  
>> over itself and
>> >> chokes to death.
>> >>
>> >> -Steve
>> >
>> > This can only happen if you use delete on a class instance. My
>> > understanding was that this is going to be removed from D2.
>>
>> Same problem without 'delete':
>>
>> class A {
>>   void dispose();
>> }
>>
>> struct B {
>>   A a;
>>   ~this() { a.dispose(); }
>> }
>>
>> class C {
>>   B b;
>> }
>>
>> C::~this(); // auto generated
>>   B::~this(); // so good so far
>>     A::dispose(); // oops!
>>
>>
>> --
>> Rainer Deyke - rainerd at eldwood.com
>
> I was posing late at night and hence made a mistake in my suggestion.
> Here's a better example of the problem:
> class A{}
> struct B{ A a; ~this(); this(ref A); }
>
> auto obj = new A();
> auto first = new B(obj);
> auto second = new B(obj);
>
> both first and second reference the same instance of A.
>
> The correct semantics for the case of a struct containing a class (more  
> generally, value type contains a reference type):
>
> the struct's dtor does NOT call the class dtor.
>
> The class dtor would be called either by the GC when it is collected or  
> when it is de-allocated by the user when its memory is managed by a  
> different memory scheme.
>
> Sorry for this confusion, it'll teach me not to post at 2AM..

So if a struct has a class reference, it cannot clean it up?  What if the  
class contains a struct that has an open file reference, and you want to  
clean up that file immediately?  What if that class is private and the  
struct knows that there are no other references to it?

Your "solution" doesn't cover any new ground, we already have the issue  
that you cannot clean up or even access heap-allocated references in  
destructors.  The problem is, you don't know from the type system that  
they are heap-allocated, and the compiler cannot know what is owned and  
what is not owned, so it can't make the call to restrict you.

What we need is a way to determine whether we can access those resources  
or not in the destructor, and it has nothing to do with struct vs. class,  
and everything to do with deterministic vs GC.  Making an artificial  
distinction on class/struct lines doesn't help.  We have the same problem,  
only worse restrictions (now I can't destroy a handle in a class on  
destruction, I need to put in a struct layer around it).

-Steve


More information about the Digitalmars-d mailing list