digitalmars.D.learn - Class deallocator not being called -- bug or oversight?
- Jarrett Billingsley (45/45) Sep 24 2007 This code:
- Jarrett Billingsley (11/12) Sep 24 2007 Some more:
- Jarrett Billingsley (4/9) Sep 24 2007 And: the earliest I can test it with is 1.010 (any earlier and I get an ...
- Sean Kelly (8/70) Sep 24 2007 You're right. This was a bug in the Tango runtime. It's now fixed in
- Regan Heath (34/38) Sep 24 2007 Works on Windows with DMD 2.004.
- Sean Kelly (5/12) Sep 24 2007 Darnit, version(0) will get me every time. That code is executed but
- Frits van Bommel (14/26) Sep 24 2007 Actually, there's an important difference:
- Sean Kelly (6/33) Sep 24 2007 You're right of course. I should really learn to not post while I'm
- Frits van Bommel (13/16) Sep 24 2007 Actually, it's not commented out; it's in a version(0) {} block (at
- Jarrett Billingsley (3/5) Sep 24 2007 Sweet, thanks.
This code: import tango.stdc.stdlib: cmalloc = malloc, cfree = free; class A { new(size_t sz) { Stdout.formatln("A new."); void* p = cmalloc(sz); if(p is null) throw new OutOfMemoryException(__FILE__, __LINE__); return p; } delete(void* p) { Stdout.formatln("A delete."); if(p is null) return; cfree(p); } this() { Stdout.formatln("A ctor."); } ~this() { Stdout.formatln("A dtor."); } } void main() { A a = new A(); delete a; } When compiled with at least DMD 1.018 (also happens with 1.021) and run, gives the output: A new. A ctor. A dtor. Where's the "A delete."? There is none. I've looked in the spec to see if I'm doing it right, and it sure looks like it. If A is made a struct (and the ctor and dtor are removed), I get: A new. A delete. As expected. Something weird is going on.
Sep 24 2007
"Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message news:fd8f6o$126d$1 digitalmars.com...Something weird is going on.Some more: Calling GC.collect() changes nothing. Adding the newly-allocated memory with GC.addRange() changes nothing, even if I then call GC.collect. The spec says that "When a delete expression .. is executed, and f is a reference to a class instance that has a deallocator, the deallocator is called with a pointer to the class instance after the destructor (if any) for the class is called." This is not happening, so I'm guessing this is a bug.
Sep 24 2007
"Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message news:fd8gau$13qi$1 digitalmars.com..."Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message news:fd8f6o$126d$1 digitalmars.com...And: the earliest I can test it with is 1.010 (any earlier and I get an ICE, presumably when compiling Tango), and the problem still exists then.Something weird is going on.Some more:
Sep 24 2007
Jarrett Billingsley wrote:This code: import tango.stdc.stdlib: cmalloc = malloc, cfree = free; class A { new(size_t sz) { Stdout.formatln("A new."); void* p = cmalloc(sz); if(p is null) throw new OutOfMemoryException(__FILE__, __LINE__); return p; } delete(void* p) { Stdout.formatln("A delete."); if(p is null) return; cfree(p); } this() { Stdout.formatln("A ctor."); } ~this() { Stdout.formatln("A dtor."); } } void main() { A a = new A(); delete a; } When compiled with at least DMD 1.018 (also happens with 1.021) and run, gives the output: A new. A ctor. A dtor. Where's the "A delete."? There is none. I've looked in the spec to see if I'm doing it right, and it sure looks like it. If A is made a struct (and the ctor and dtor are removed), I get: A new. A delete. As expected. Something weird is going on.You're right. This was a bug in the Tango runtime. It's now fixed in the Tango trunk for both DMD and GDC. Oh for what it's worth, I can't figure out where Phobos is calling class deallocators--the block I'd expect to be used in internal/gc/gc.d is commented out. I don't suppose someone could test this with Phobos to see if it works? Sean
Sep 24 2007
Sean Kelly wrote:Oh for what it's worth, I can't figure out where Phobos is calling class deallocators--the block I'd expect to be used in internal/gc/gc.d is commented out. I don't suppose someone could test this with Phobos to see if it works?Works on Windows with DMD 2.004. import std.stdio; import std.c.stdlib; class A { new(size_t sz) { writefln("A new."); void* p = malloc(sz); return p; } delete(void* p) { writefln("A delete."); if(p is null) return; free(p); } this() { writefln("A ctor."); } ~this() { writefln("A dtor."); } } void main() { A a = new A(); delete a; } Regan
Sep 24 2007
Regan Heath wrote:Sean Kelly wrote:Darnit, version(0) will get me every time. That code is executed but it's the same as the old buggy Tango impl. Ah well, as long as it works in Phobos... SeanOh for what it's worth, I can't figure out where Phobos is calling class deallocators--the block I'd expect to be used in internal/gc/gc.d is commented out. I don't suppose someone could test this with Phobos to see if it works?Works on Windows with DMD 2.004.
Sep 24 2007
Sean Kelly wrote:Regan Heath wrote:Actually, there's an important difference: In Phobos the finalizer hander is only called from _d_delclass directly when a deallocator is present, necessarily *after* the classinfo reference has been loaded from the vtable since the deallocator is stored in the classinfo. (If no deallocator is present, the finalizer handler is called from somewhere inside _gc.free()). In Tango, on the other hand, you always call the finalizer handler from _d_delclass. You used to do this *before* loading the classinfo reference from the vtable. Now for the important bit: in both libs, the finalizer handler _nulls the vptr_. That means that in Tango it used to do so before the lookup of the classinfo in the vtable, while in Phobos the classinfo lookup was always performed before the finalizer handler is called.Sean Kelly wrote:Darnit, version(0) will get me every time. That code is executed but it's the same as the old buggy Tango impl. Ah well, as long as it works in Phobos...Oh for what it's worth, I can't figure out where Phobos is calling class deallocators--the block I'd expect to be used in internal/gc/gc.d is commented out. I don't suppose someone could test this with Phobos to see if it works?Works on Windows with DMD 2.004.
Sep 24 2007
Frits van Bommel wrote:Sean Kelly wrote:You're right of course. I should really learn to not post while I'm still waking up :-)Regan Heath wrote:Actually, there's an important difference: In Phobos the finalizer hander is only called from _d_delclass directly when a deallocator is present, necessarily *after* the classinfo reference has been loaded from the vtable since the deallocator is stored in the classinfo. (If no deallocator is present, the finalizer handler is called from somewhere inside _gc.free()). In Tango, on the other hand, you always call the finalizer handler from _d_delclass. You used to do this *before* loading the classinfo reference from the vtable.Sean Kelly wrote:Darnit, version(0) will get me every time. That code is executed but it's the same as the old buggy Tango impl. Ah well, as long as it works in Phobos...Oh for what it's worth, I can't figure out where Phobos is calling class deallocators--the block I'd expect to be used in internal/gc/gc.d is commented out. I don't suppose someone could test this with Phobos to see if it works?Works on Windows with DMD 2.004.Now for the important bit: in both libs, the finalizer handler _nulls the vptr_. That means that in Tango it used to do so before the lookup of the classinfo in the vtable, while in Phobos the classinfo lookup was always performed before the finalizer handler is called.Yup. In hindsight, the side-effect makes sense, but I'd overlooked it when changing the behavior of _d_delclass way back when. Sean
Sep 24 2007
Sean Kelly wrote:Oh for what it's worth, I can't figure out where Phobos is calling class deallocators--the block I'd expect to be used in internal/gc/gc.d is commented out.Actually, it's not commented out; it's in a version(0) {} block (at least in my copy of Phobos) . A "version(0)" doesn't have any effect though. From the spec: --- The VersionCondition is satisfied if the Integer is greater than or equal to the current version level, or if Identifier matches a version identifier. --- Since 0 seems to be the minimum level (DMD won't let me specify a negative "version level") the code will always be executed (similar to "version(all)").
Sep 24 2007
"Sean Kelly" <sean f4.ca> wrote in message news:fd8m9v$1cgh$1 digitalmars.com...You're right. This was a bug in the Tango runtime. It's now fixed in the Tango trunk for both DMD and GDC.Sweet, thanks.
Sep 24 2007