destructor order

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Sat Feb 26 16:06:30 PST 2011


On 1/26/11 12:18 PM, Steven Schveighoffer wrote:
> 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

Thanks for taking this to completion! I had it on my todo list forever.

Andrei


More information about the Digitalmars-d mailing list