Thread overview
What is legal in a destructor?
Aug 27, 2006
Lutger
Aug 29, 2006
Sean Kelly
August 27, 2006
I'm having some trouble understanding exactly what is and what isn't legal to do in a (non-auto) destructor. I'm thinking about these specifically:

- using the 'this' pointer as a parameter to make calls to another (from another class or free) function.
- calling member functions.
- referencing delegates to member functions.
- referencing data fields with types like int.

Also, is there a way to have the garbage collector run and collect dead objects without the delete expression, so as to experiment with the behavior?

The spec says: "When the garbage collector calls a destructor for an object of a class that has members that are references to garbage collected objects, those references are no longer valid. This means that destructors cannot reference sub objects. This rule does not apply to auto objects or objects deleted with the DeleteExpression."
August 27, 2006
Lutger wrote:
> Also, is there a way to have the garbage collector run and collect dead objects without the delete expression, so as to experiment with the behavior?

# static import std.gc ;
#
# class Foo {
#   /* ... */
# }
#
# void main () {
#   Foo f = new Foo;
#   f = null;
#   std.gc.fullCollect();
# }

http://digitalmars.com/d/phobos/std_gc.html

-- Chris Nicholson-Sauls
August 27, 2006
"Lutger" <lutger.blijdestijn@gmail.com> wrote in message news:ecruhp$2hug$1@digitaldaemon.com...
> I'm having some trouble understanding exactly what is and what isn't legal to do in a (non-auto) destructor. I'm thinking about these specifically:
>
> - using the 'this' pointer as a parameter to make calls to another (from
> another class or free) function.
> - calling member functions.
> - referencing delegates to member functions.
> - referencing data fields with types like int.

As a general rule, you shouldn't try to access any GC'ed memory within a destructor.  This means most things allocated by your program, such as references to other class instances, arrays, and blocks of memory allocated by 'new'.  When the destructor is run, the 'this' pointer is still valid, so you can call other member functions and use it as a parameter, but again, those functions shouldn't access GC'ed memory.

I mostly use destructors to clean up non-GC'ed resources, such as system resources (file handles, COM interfaces etc.).  I also set references to GC'ed memory to null, which isn't really required, but it might make the GC's job a little easier.


August 29, 2006
Lutger wrote:
> I'm having some trouble understanding exactly what is and what isn't legal to do in a (non-auto) destructor. I'm thinking about these specifically:
> 
> - using the 'this' pointer as a parameter to make calls to another (from another class or free) function.
> - calling member functions.
> - referencing delegates to member functions.

The three above things are only legal if the functions are final or if you can be certain you are calling them from the most derived class instance.  Otherwise, there is a possibility that you will be calling into an already destroyed portion of the object.  For example:

class C {
    ~this() { fn(); }
    void fn() { printf( "default impl\n" ); }
}

class D : C {
    this() { val = cast(int*)malloc(int.sizeof); *val = 5; }
    ~this() { free(val); }
    void fn() { printf( "%d\n", *val ); }
private int* val;
}

D d = new D;
delete d;

Here, C's dtor calls the virtual function fn, which attempts to print val after the memory allocated for val has been freed by D's dtor.  So the function may print garbage or you may get an access violation.

> - referencing data fields with types like int.

Should be fine.


Sean