Bug 21989 – [REG 2.096] Double destruction of new'ed aggregates since `-preview=dtorfields` became the default

Status
NEW
Severity
regression
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2021-06-02T11:53:51Z
Last change time
2024-12-13T19:16:45Z
Keywords
industry, pull, wrong-code
Assigned to
No Owner
Creator
Mathias LANG
Moved to GitHub: dmd#18037 →

Comments

Comment #0 by pro.mathias.lang — 2021-06-02T11:53:51Z
```D import std; pragma(msg, __VERSION__); class Test { S s; this() { if (uniform(1, 10) != 0) throw new Exception("oops"); s = S(13); } } struct S { int x = 42; int y; this(int y) { this.y = y; }; this(this) { assert(x == 42); } ~this() { if (x != 42) writeln("OH NO!"); x = 0; // omitting this makes "OH NO!" go away } } void main() { try new Test; catch (Exception e) writeln("Expected fail: ", e.msg); } ``` Result: ``` 2096L Expected fail: oops OH NO! ``` This happens because the class ctor destructs it, then the GC, upon collecting the object, finalize the class again.
Comment #1 by pro.mathias.lang — 2021-06-02T11:54:25Z
Bug found in a large application using Vibe.d: https://github.com/vibe-d/vibe-core/issues/283
Comment #2 by moonlightsentinel — 2021-06-02T12:40:42Z
Thats bad. I guess the destructed class instance should be GC.free'd if the ctor is aborted by an exception. Alternatively could also reset the instance to it's init value.
Comment #3 by moonlightsentinel — 2021-06-06T11:30:07Z
Not restricted to classes, also affects GC-allocated structs
Comment #4 by dlang-bot — 2021-06-06T15:09:57Z
@MoonlightSentinel created dlang/dmd pull request #12641 "Fix 21989 - Reset destructed instance with preview=dtorfields" fixing this issue: - Fix 21989 - Reset destructed instance with preview=dtorfields Emplacing the initializer ensures that the GC won't run the destructor on an invalid instance. Preventing the destructor call from the GC doesn't seem to be feasible due to the potentually lesser qualified GC interface (not `pure`, ...). https://github.com/dlang/dmd/pull/12641
Comment #5 by info — 2023-11-11T06:46:46Z
It seems that in 2.103.0 this bug was fixed; atleast the provided example doesn't produces the "OH NO!" anymore: ``` 2103L Expected fail: oops ```
Comment #6 by robert.schadek — 2024-12-13T19:16:45Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/18037 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB