www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 9704] New: Destructor not called on function calls if postblit throws

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

           Summary: Destructor not called on function calls if postblit
                    throws
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: normal
          Priority: P2
         Component: DMD
        AssignedTo: nobody puremagic.com
        ReportedBy: johannespfau gmail.com



PDT ---
See the attached testcase:

If the throw statement in B's postblit is commented we see the expected result:
A:this(this)
B:this(this)
A:~this
B:~this
B:~this
A:~this

The function call creates two copies, then the destructors are called for the
originals and for the copies. But if the throw statement is in place:
A:this(this)
B:this(this)
B:~this
A:~this
object.Exception test99.d(12): Boom

We see that the destructors for the copies are not called. It can be argued
that this is valid for the B copy, as it's postblit threw.

But for the copy of A the destructor must be called as the postblit was called
and succeeded.


The problem is that the destructors are currently called in the callee but the
postblits in the caller. If an exception is thrown in between those calls, the
destructor can't be called.

A possible solution is to move the destructor to the caller. But in this case
the parameter (the copy) must be passed by invisible reference so that the
destructor actually sees the updated value after the callee returns.

(Note that it might be useful to make an exception for non-PODs without
destructors here. Those shouldn't be affected by this issue and could be
treated like PODs when being passed to a function as an optimization.)

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




PDT ---
Created an attachment (id=1201)
test case

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


Maxim Fomin <maxim maxim-fomin.ru> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |maxim maxim-fomin.ru



---

 The problem is that the destructors are currently called in the callee but the
 postblits in the caller. If an exception is thrown in between those calls, the
 destructor can't be called.
To be more precise, it happens during evaluation of function argument which follows some struct argument and throws exception. extern(C) int printf(const char* fmt, ...); struct A { this(this) { printf("A:this(this)\n");} ~this() { printf("A:~this\n"); } uint data; } int foo() { throw new Exception(""); } void func(A a, int i) {} void main() { A a; func(a, foo()); } Here should be two destructors: for "a" and " __cpcttmpXXX" structs. And calling dtor is unavoidable since postblit may deep copy some memory.
 A possible solution is to move the destructor to the caller. But in this case
 the parameter (the copy) must be passed by invisible reference so that the
 destructor actually sees the updated value after the callee returns.
 
 (Note that it might be useful to make an exception for non-PODs without
 destructors here. Those shouldn't be affected by this issue and could be
 treated like PODs when being passed to a function as an optimization.)
Alternatively a copy operation can be moved into callee or D runtime can be boosted to cope with such problem. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 12 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9704


monarchdodra gmail.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |andrei erdani.com



*** Issue 10623 has been marked as a duplicate of this issue. ***

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


monarchdodra gmail.com changed:

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




 *** Issue 10623 has been marked as a duplicate of this issue. ***
For reference, this was also discussed in learn. http://forum.dlang.org/group/digitalmars.D.learn http://forum.dlang.org/thread/20130628005448.00000969 unknown -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jul 12 2013
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=9704




PDT ---
Pasting the additional example here for reference:

import std.stdio;

struct S1 { 
    this(int) { writeln("constructed"); } 
    ~this() { writeln("destroyed"); } 
}
struct S2 { this(int) { throw new Exception("a"); } }

void fun(S1, S2, S1) {}

void main()
{
    fun(S1(2), S2(2), S1(2));
}

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jul 12 2013