Bug 6437 – Refcounted calls dtor before ctor, never calls dtor for globals

Status
RESOLVED
Resolution
FIXED
Severity
major
Priority
P2
Component
phobos
Product
D
Version
D2
Platform
Other
OS
Windows
Creation time
2011-08-04T14:23:00Z
Last change time
2012-04-19T18:34:00Z
Assigned to
nobody
Creator
andrej.mitrovich

Comments

Comment #0 by andrej.mitrovich — 2011-08-04T14:23:06Z
module globaldtors; import std.typecons; import std.stdio; struct Foo { struct Payload { this(int x) { writeln("constructor called"); } ~this() { writeln("destructor called"); } this(this) { assert(false); } void opAssign(Foo.Payload rhs) { assert(false); } } private alias RefCounted!(Payload, RefCountedAutoInitialize.yes) Data; Data data; this (int x) { data = Data(x); } } Foo foo; void main() { /+ + destructor called <- this should not happen + constructor called + <- where's the dtor call? +/ // foo = Foo(1); /+ + destructor called <- this should not happen + constructor called + destructor called +/ // auto bar = Foo(1); } Uncomment the two assignments individually to verify they print what's in the comments. Regardless if it's a global or not, a dtor is being called first for some reason, this looks like a bug. But if the variable is also a global (TLS/shared doesn't matter), the dtor is not called on application exit.
Comment #1 by kiithsacmp — 2012-01-12T12:29:56Z
The destructor call seems to happen in struct specialization of emplace(), which is called from RefCounted._RefCounted.initialize() . The result variable in emplace() has its destructor called when it goes out of scope.(In reply to comment #0) > module globaldtors; > import std.typecons; > > import std.stdio; > > struct Foo > { > struct Payload > { > this(int x) > { > writeln("constructor called"); > } > > ~this() > { > writeln("destructor called"); > } > > this(this) { assert(false); } > void opAssign(Foo.Payload rhs) { assert(false); } > } > > private alias RefCounted!(Payload, RefCountedAutoInitialize.yes) Data; > Data data; > > this (int x) > { > data = Data(x); > } > } > > Foo foo; > > void main() > { > /+ > + destructor called <- this should not happen > + constructor called > + <- where's the dtor call? > +/ > // foo = Foo(1); > > > /+ > + destructor called <- this should not happen > + constructor called > + destructor called > +/ > // auto bar = Foo(1); > } > > Uncomment the two assignments individually to verify they print what's in the > comments. Regardless if it's a global or not, a dtor is being called first for > some reason, this looks like a bug. > > But if the variable is also a global (TLS/shared doesn't matter), the dtor is > not called on application exit.
Comment #2 by sandford — 2012-03-09T11:52:30Z
I just tried the example in D 2.058 and the extra dtors appear to have been fixed. The issue with globals and destruction still exists. For now, you can work around the problem using static ~this() { typeid(foo).destroy(&foo1); }
Comment #3 by andrej.mitrovich — 2012-04-19T18:34:00Z
(In reply to comment #2) > I just tried the example in D 2.058 and the extra dtors appear to have been > fixed. The issue with globals and destruction still exists. For now, you can > work around the problem using > > static ~this() { typeid(foo).destroy(&foo1); } Yes it's fixed, thanks. The globals issue isn't really a bug since destruction of globals isn't guaranteed (IIRC the docs were updated recently to acknowledge this).