www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 9335] New: Dtors are not called for dynamic arrays initialized by literals

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9335

           Summary: Dtors are not called for dynamic arrays initialized by
                    literals
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: normal
          Priority: P2
         Component: DMD
        AssignedTo: nobody puremagic.com
        ReportedBy: maxim maxim-fomin.ru


--- Comment #0 from Maxim Fomin <maxim maxim-fomin.ru> 2013-01-17 08:34:20 PST
---
Dynamic arrays of structs initialized by array literals go out of scope without
calling destructors. This does not happen with static arrays.

import std.stdio : writefln;

struct S
{
    int i;
    this(this) { writefln("%X postbit", i); i = 0;}
    ~this() { writefln("%X dtor", i); }
}

void main()
{
    S[] arr = [S()];
}

Issue is maked as dmd issue, because druntime cannot call destructors when AA
array goes out of the scope.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jan 17 2013
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9335


monarchdodra gmail.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |monarchdodra gmail.com
           See Also|                            |http://d.puremagic.com/issu
                   |                            |es/show_bug.cgi?id=9334


--- Comment #1 from monarchdodra gmail.com 2013-01-17 08:39:31 PST ---
(In reply to comment #0)
 Dynamic arrays of structs initialized by array literals go out of scope without
 calling destructors. This does not happen with static arrays.
 
 import std.stdio : writefln;
 
 struct S
 {
     int i;
     this(this) { writefln("%X postbit", i); i = 0;}
     ~this() { writefln("%X dtor", i); }
 }
 
 void main()
 {
     S[] arr = [S()];
 }
 
 Issue is maked as dmd issue, because druntime cannot call destructors when AA
 array goes out of the scope.

Same answer as in http://d.puremagic.com/issues/show_bug.cgi?id=9334. The array is allocated dynamically, and makes no promises it will release at the end of the scope, or of the program. I'm not sure what you mean by "array literals", but you'll get the same behavior with: S[] arr = new S[](5); -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 17 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9335



--- Comment #2 from Maxim Fomin <maxim maxim-fomin.ru> 2013-01-17 10:07:54 PST
---
(In reply to comment #1)
 Same answer as in http://d.puremagic.com/issues/show_bug.cgi?id=9334.
 
 The array is allocated dynamically, and makes no promises it will release at
 the end of the scope, or of the program.
 
 I'm not sure what you mean by "array literals", but you'll get the same
 behavior with:
 S[] arr = new S[](5);

Well, situation here is different than in issue 9334 import core.stdc.stdio : printf; struct S { int i; this(this) { printf("%X postbit\n", i); i = 0;} ~this() { printf("%X dtor\n", i); } } void main() { S[] arr = [S()]; } Dump of assembler code for function _Dmain: 0x0000000000418894 <+0>: push %rbp 0x0000000000418895 <+1>: mov %rsp,%rbp 0x0000000000418898 <+4>: sub $0x10,%rsp 0x000000000041889c <+8>: movabs $0x1,%rsi 0x00000000004188a6 <+18>: movabs $0x6362a0,%rdi 0x00000000004188b0 <+28>: callq 0x41a610 <_d_arrayliteralTX> 0x00000000004188b5 <+33>: xor %ecx,%ecx 0x00000000004188b7 <+35>: mov %ecx,-0x8(%rbp) 0x00000000004188ba <+38>: lea -0x8(%rbp),%rsi 0x00000000004188be <+42>: mov %rax,%rdi 0x00000000004188c1 <+45>: movsb %ds:(%rsi),%es:(%rdi) 0x00000000004188c2 <+46>: movsb %ds:(%rsi),%es:(%rdi) 0x00000000004188c3 <+47>: movsb %ds:(%rsi),%es:(%rdi) 0x00000000004188c4 <+48>: movsb %ds:(%rsi),%es:(%rdi) 0x00000000004188c5 <+49>: mov %rax,%rdx 0x00000000004188c8 <+52>: movabs $0x1,%rax 0x00000000004188d2 <+62>: mov %rcx,%rax 0x00000000004188d5 <+65>: leaveq 0x00000000004188d6 <+66>: retq End of assembler dump. Array literal is allocated by _d_arrayliteralTX, yet is initialized by a stack temporary S(). Where a dtor call on it? The behavior is in contrast to issue 9334 when a dtor in similar situation is called. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 17 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9335


Temtaime <temtaime gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |temtaime gmail.com


--- Comment #3 from Temtaime <temtaime gmail.com> 2013-06-25 02:00:59 PDT ---
Dump.
Can someone fix that and 9334? It's critical bug for me.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jun 25 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9335


yebblies <yebblies gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |yebblies gmail.com
          Component|DMD                         |druntime


--- Comment #4 from yebblies <yebblies gmail.com> 2013-06-28 22:43:04 EST ---
This is a druntime problem.  The destructor should be called for each element
in the array when it is collected by the GC.

There is no need to call the destructor or postblit when moving the stack
allocated structs to the heap, it is legal to move them with memcpy.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jun 28 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9335



--- Comment #5 from Temtaime <temtaime gmail.com> 2013-06-28 05:48:19 PDT ---
Stop. Why GC collects it?
Destructor should be called when declaration scope ends.
This is array of structs, not of classes.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jun 28 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9335



--- Comment #6 from yebblies <yebblies gmail.com> 2013-06-28 23:04:08 EST ---
(In reply to comment #5)
 Stop. Why GC collects it?
 Destructor should be called when declaration scope ends.
 This is array of structs, not of classes.

void main() { S[] arr = [S()]; } This is an array of structs, and the array is on the heap. This would be an array on the stack: void main() { S[1] arr = [S()]; } -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jun 28 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9335


Steven Schveighoffer <schveiguy yahoo.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |schveiguy yahoo.com


--- Comment #7 from Steven Schveighoffer <schveiguy yahoo.com> 2013-06-28
07:11:09 PDT ---
The GC does not have any idea what type of data is in this block.  It cannot
call dtors, all it sees is a void * with no indication that it has a finalizer.
 In order for this to work, we need better record keeping by the GC.

It's definitely a druntime/GC problem, not a dmd problem.

Perhaps Rainer's precise GC stores enough information?  not sure.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jun 28 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9335



--- Comment #8 from Maxim Fomin <maxim maxim-fomin.ru> 2013-06-28 07:42:41 PDT
---
(In reply to comment #4)
 There is no need to call the destructor or postblit when moving the stack
 allocated structs to the heap, it is legal to move them with memcpy.

Issue here is not in non-calling destructor when object is moved from stack to heap by pointer but is in non-calling destructor for temporary. This contradicts to policy in issue 9334 (which is itself not stable). General problem here is that dmd (unexpectedly) sometimes initializes variables with temporaries and sometimes not. When it does initialize objects with a temporary, sometimes it calls destructors on it and sometimes not. Such game with temporaries and destructors causes bugs. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jun 28 2013
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9335



--- Comment #9 from yebblies <yebblies gmail.com> 2013-06-29 00:55:21 EST ---
(In reply to comment #8)
 (In reply to comment #4)
 There is no need to call the destructor or postblit when moving the stack
 allocated structs to the heap, it is legal to move them with memcpy.

Issue here is not in non-calling destructor when object is moved from stack to heap by pointer but is in non-calling destructor for temporary. This contradicts to policy in issue 9334 (which is itself not stable).

The temporary you are talking about is the struct that is being moved to the heap. D allows a struct to be moved with a memcpy. 9334 aside, what is happening here is valid. 1. Structs are constructed on the stack 2. Heap array space is allocated 3. Structs are bit-copied into the heap memory 4. The original stack structs are abandoned Because only one copy of the structs exists at the end, there is no copy, only a move.
 General problem here is that dmd (unexpectedly) sometimes initializes >
variables
 with temporaries and sometimes not. When it does initialize objects with a

 with temporaries and destructors causes bugs.

dmd is free to choose either making a copy (which means calling the postblit, then the destructor of the temporary) or to do a move (bitcopy) like it is doing here. The main difference is that a move has better performance. Both are valid. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jun 28 2013