Bug 22177 – emplace should handle throwing constructors

Status
NEW
Severity
normal
Priority
P3
Component
druntime
Product
D
Version
D2
Platform
All
OS
All
Creation time
2021-08-04T20:39:44Z
Last change time
2024-12-07T13:41:16Z
Assigned to
No Owner
Creator
kinke
Moved to GitHub: dmd#17426 →

Comments

Comment #0 by kinke — 2021-08-04T20:39:44Z
This segfaults with v2.097.1: ``` extern(C) void free(void* p); struct S { void* p; this(int) { p = cast(void*) 0xdeadbeef; throw new Exception("blub"); } ~this() { if (p) free(p); } } void regular() { try { auto s = S(0); // not destructed because not successfully constructed } catch (Exception) {} } void empl() { import core.lifetime; try { S s = void; emplace(&s, 0); } // `s` is destructed but in no well-defined state - boom catch (Exception) {} } void main() { regular(); empl(); } ``` The emplace family (incl. copyEmplace for throwing postblit/copy constructor) should take care of resetting the instance to `T.init` in case of a throw, so that (unavoidable) destruction is well-defined. It should probably only do so if an Exception is thrown (as opposed to an Error), to avoid the overhead for `nothrow` constructors. This was suggested here: https://github.com/dlang/druntime/pull/3483#discussion_r682629332
Comment #1 by kinke — 2021-08-04T20:45:10Z
Works since v2.096.
Comment #2 by kinke — 2021-08-04T20:45:55Z
Dammit, wrong tab. ;)
Comment #3 by stanislav.blinov — 2021-11-27T08:36:52Z
I think the language should specify (as in, explicitly state in the spec) the expected state of an object in case its ctor throws. IMO it should be the user's job to leave their objects in a destructible state. Perhaps something like: "If a constructor throws an exception, the object MAY still be destructed. Therefore, constructors should always leave objects in a destructible state." Pseudo-code for emplace is: emplaceInitializer(ptr); constructAt(ptr, args); Thus it makes little sense to write the initializer again. User was given a piece of memory, it's theirs now to keep tidy. It follows then that it should be the user's responsibility to maintain exception safety in their ctors. An outlier here is emplacement of arrays, where it does make sense to write .init into the remainder of array if an exception was thrown, as that *is* assumed to contain garbage state. Overwriting partially-constructed state with .init can potentially be problematic sine can cause resource leaks.
Comment #4 by stanislav.blinov — 2021-11-27T08:38:07Z
*since it can. Typing before coffee...
Comment #5 by robert.schadek — 2024-12-07T13:41:16Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/17426 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB