destructor order

Steven Schveighoffer schveiguy at yahoo.com
Wed Jan 26 10:18:58 PST 2011


On Wed, 26 Jan 2011 12:26:22 -0500, Andrei Alexandrescu  
<SeeWebsiteForEmail at erdani.org> wrote:

> On 1/26/11 10:17 AM, Steven Schveighoffer wrote:
>> On Wed, 26 Jan 2011 11:09:45 -0500, Andrej Mitrovic
>> <andrej.mitrovich at gmail.com> wrote:
>>
>>> I think I glanced over a recent svn commit that fixed this, though I'm
>>> not sure.
>>
>> No, it hasn't been fixed.
>>
>> The fix is *really* simple, just have clear call rt_finalize (as Sean
>> pointed out on the mailing list)
>>
>> -Steve
>
> Steve, if you could point out what I need to do I'll be glad to do it  
> right now. Better yet, feel free to try your hand at a git commit. It's  
> fun!

*sweats nervously* I don't know, I'd like to read about how git works  
before doing a commit.  I don't really understand it at all, I had the  
same problem with subversion when I started using it.

The fix is really easy, just change clear to this:

void clear(T)(T obj) if (is(T == class))
{
   rt_finalize(cast(void*)obj);
}

Here is the body of the current clear:

     if (!obj) return;
     auto ci = obj.classinfo;
     auto defaultCtor =
         cast(void function(Object)) ci.defaultConstructor;
     version(none) // enforce isn't available in druntime
         _enforce(defaultCtor || (ci.flags & 8) == 0);
     immutable size = ci.init.length;

     auto ci2 = ci;
     do
     {
         auto dtor = cast(void function(Object))ci2.destructor;
         if (dtor)
             dtor(obj);
         ci2 = ci2.base;
     } while (ci2)

     auto buf = (cast(void*) obj)[0 .. size];
     buf[] = ci.init;
     if (defaultCtor)
         defaultCtor(obj);

And the body of rt_finalize

     if (p) // not necessary if called from gc
     {
         ClassInfo** pc = cast(ClassInfo**)p;

         if (*pc)
         {
             ClassInfo c = **pc;
             byte[] w = c.init;

             try
             {
                 if (det || collectHandler is null ||  
collectHandler(cast(Object)p))
                 {
                     do
                     {
                         if (c.destructor)
                         {
                             fp_t fp = cast(fp_t)c.destructor;
                             (*fp)(cast(Object)p); // call destructor
                         }
                         c = c.base;
                     } while (c);
                 }
                 if ((cast(void**)p)[1]) // if monitor is not null
                     _d_monitordelete(cast(Object)p, det);
                 (cast(byte*) p)[0 .. w.length] = w[];
             }
             catch (Throwable e)
             {
                 onFinalizeError(**pc, e);
             }
             finally
             {
                 *pc = null; // zero vptr
             }
         }
     }

Note the eerie similarities :)

-Steve


More information about the Digitalmars-d mailing list