Bug 15009 – Object.destroy calls unnecessary postblits for destruction of static arrays object

Status
RESOLVED
Resolution
FIXED
Severity
major
Priority
P1
Component
druntime
Product
D
Version
D2
Platform
All
OS
All
Creation time
2015-09-03T18:01:00Z
Last change time
2015-10-04T18:19:19Z
Keywords
pull
Assigned to
nobody
Creator
nicolas.jinchereau

Comments

Comment #0 by nicolas.jinchereau — 2015-09-03T18:01:23Z
struct S { int x; this(int x) { writeln("ctor"); } this(this) { writeln("ctor(postblit)"); } ~this() { writeln("dtor"); } } void main(string[] args) { S[2]* arr = cast(S[2]*)calloc(1, S.sizeof); emplace(arr, S(1)); destroy(*arr); free(arr); } output has 5 ctors, and 3 dtors: ctor ctor(postblit) ctor(postblit) dtor ctor(postblit) dtor ctor(postblit) dtor fix is to modify this overload of Object.destroy: void destroy(T : U[n], U, size_t n)(ref T obj) if (!is(T == struct)) { typeid(T).destroy(&obj); // +++ obj[] = U.init; } output now has 5 ctors, and 5 dtors, as expected: ctor ctor(postblit) ctor(postblit) dtor dtor dtor ctor(postblit) dtor ctor(postblit) dtor
Comment #1 by k.hara.pg — 2015-09-03T21:23:47Z
The bug in Object.destroy overload for the static array is, that is using block assignment. void destroy(T : U[n], U, size_t n)(ref T obj) if (!is(T == struct)) { obj[] = U.init; } obj[] = U.init; _copies_ the rhs for each elements of lhs, and destroys the original elements of lhs. Instead of that, it should just destroy the elements. And, the order of destroying should occur from the last to the first. Then' the fixed destroy function should be: void destroy(T : U[n], U, size_t n)(ref T obj) if (!is(T == struct)) { foreach_reverse (ref e; obj[]) e = U.init; }
Comment #2 by k.hara.pg — 2015-09-03T21:41:33Z
Note that, destroy actually calls destructors. import std.stdio, std.conv, core.stdc.stdlib; struct S { int x; this(int x) { writeln("ctor"); } this(this) { writeln("ctor(postblit)"); } ~this() { writeln("dtor"); } } void main(string[] args) { S[2]* arr = cast(S[2]*)calloc(1, S.sizeof); printf("-- calloc done\n"); emplace(arr, S(1)); printf("-- emplace done\n"); destroy(*arr); printf("-- destroy done\n"); //typeid(*arr).destroy(&arr); free(arr); printf("-- free done\n"); } output is: $ dmd -run test -- calloc done ctor ctor(postblit) ctor(postblit) dtor -- emplace done ctor(postblit) dtor ctor(postblit) dtor -- destroy done -- free done My point is , the two postblit calls invoked by destroy() is unnecessary.
Comment #3 by k.hara.pg — 2015-09-03T21:59:26Z
Comment #4 by nicolas.jinchereau — 2015-09-03T22:02:46Z
works as expected. Thanks =)
Comment #5 by github-bugzilla — 2015-09-05T12:02:32Z
Commits pushed to master at https://github.com/D-Programming-Language/druntime https://github.com/D-Programming-Language/druntime/commit/5be4156ccba77b49c7232060bbecb8b2527a8287 fix Issue 15009 - Object.destroy calls unnecessary postblits for destruction of static arrays object https://github.com/D-Programming-Language/druntime/commit/3dc4e28ba997954deeb1f8db63051ba1f03e0463 Merge pull request #1376 from 9rnsr/fix15009 Issue 15009 - Object.destroy calls unnecessary postblits for destruction of static arrays object
Comment #6 by github-bugzilla — 2015-10-04T18:19:19Z
Commits pushed to stable at https://github.com/D-Programming-Language/druntime https://github.com/D-Programming-Language/druntime/commit/5be4156ccba77b49c7232060bbecb8b2527a8287 fix Issue 15009 - Object.destroy calls unnecessary postblits for destruction of static arrays object https://github.com/D-Programming-Language/druntime/commit/3dc4e28ba997954deeb1f8db63051ba1f03e0463 Merge pull request #1376 from 9rnsr/fix15009