www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - Explicit Class Instance Allocation causes Segfault

With dmd v0.102, the following code causes a Linux Segfault (or Win32 Exception)
when delete is called on the object. This is basically the same code found in
the docs. here: http://digitalmars.com/d/memory.html#newdelete

#import std.outofmemory;
#import std.c.stdlib;
#import std.gc;

#class Foo
#{
#    new(uint sz)
#    {
#       void* p;
#
#       p = std.c.stdlib.malloc(sz);
#       if (!p)
#           throw new OutOfMemory();
#       addRange(p, p + sz);
#       return p;
#   }
#
#   delete(void* p)
#   {
#       if (p)
#       {   removeRange(p);
#           std.c.stdlib.free(p);
#       }
#   }
#}

#void main()
#{
#    Foo f = new Foo;
#    delete f;
#}

The segfault happens when the destructor is called (even though there isn't one
for the class above ;).

#extern (C)
#void _d_callfinalizer(void *p)
#{
#    //printf("_d_callfinalizer(p = %p)\n", p);
#    if (p)  // not necessary if called from gc
#    {
#    ClassInfo **pc = cast(ClassInfo **)p;
#    if (*pc)
#    {
#        ClassInfo c = **pc;
#
#        do
#        {
#        if (c.destructor)
#        {
#            fp_t fp = cast(fp_t)c.destructor;
#            (*fp)(cast(Object)p); // call destructor <-- SEGFAULT here -->
#        }
#        c = c.base;
#        } while (c);
#        if ((cast(void**)p)[1]) // if monitor is not null
#        _d_monitorrelease(cast(Object)p);
#        *pc = null;         // zero vptr
#    }
#   }
#}

If the call to _d_finalizer in _d_delclass is commented out, the segfault
happens when the deallocator is called.

#void _d_delclass(Object *p)
#{
#    if (*p)
#    {
#    debug (PRINTF) printf("_d_delclass(%p)\n", *p);
#    version(0)
#    {
#        ClassInfo **pc = cast(ClassInfo **)*p;
#        if (*pc)
#        {
#        ClassInfo c = **pc;
#
#        if (c.deallocator)
#        {
#            //_d_callfinalizer(*p);
#            fp_t fp = cast(fp_t)c.deallocator;
#            (*fp)(*p);          // call deallocator // <-- SEGFAULT -->
#            *p = null;
#            return;
#        }
#        }
#    }
#    _gc.free(*p);
#    *p = null;
#    }
#}

Looks like maybe the ClassInfo initialization isn't happening correctly.

- Dave
Sep 27 2004