www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 4147] New: Failing inner expression leaves ghost-reference to outer expression on GC which is errenously finalized

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

           Summary: Failing inner expression leaves ghost-reference to
                    outer expression on GC which is errenously finalized
           Product: D
           Version: future
          Platform: x86
        OS/Version: Windows
            Status: NEW
          Severity: major
          Priority: P2
         Component: DMD
        AssignedTo: nobody puremagic.com
        ReportedBy: webmaster aj-productions.de



11:14:25 PDT ---
Created an attachment (id=620)
Demonstration of the bug - define "DEMO_FAILURE" during compilation to see the
bug in action.

Using the latest DMD 2.043.

Please refer to the attachment for a complete example. In short...

Given the following expression:
"auto parent = new Parent( new FailingChild() );".

"FailingChild::this()" throws an exception and "Parent::this( ... )" never gets
called.

The problem: The GC tries to finalize "parent", despite it has never been
constructed.

This
- compromised exception safety.
- causes hard-to-find bugs in large scale frameworks, since code is executed in
objects that the programmer is not even aware of.


Without knowing the excact implementation details of the GC, my "guess" on the
problem is: A GC-root to "parent" is added, before "FailingChild::this()" is
evaluated.

My "guess" on the solution: Add the GC-root to "parent" after the inner
expression "FailingChild::this()" is evaluated.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
May 02 2010
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4147


nfxjfg gmail.com changed:

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



Here is a somewhat reduced test case:

class Parent { this( Object c ) { assert(false, "a"); } ~this() { assert( false, "b" ); } } Object foo() { throw new Exception( "Some error" ); } void main() { try { auto parent = new Parent( foo() ); } catch (Exception e) { } } <<<< This fails with assertion b (the dtor), even though the constructor (assertion a) was never called. Disassembly proves that a new object is allocated, before foo() and the ctor of Parent is called. Possible solutions: - allow the runtime to run the dtor/finalizer only if the ctor was called (set a flag immediately before calling the ctor or so) - allocate the object only immediately before calling the ctor I'm not sure if Walter would agree that this is a bug. The dtor gets called even if the ctor fails by throwing an exception. In general, the user has to be very careful with finalizers: using finalizers is full of synchronization issues, trouble caused by not being allowed to access references, and so on. Basically a programmer's trap. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
May 02 2010
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4147




Finalizers called by the GC should be consistent with scope classes and struct
ctors/dtors. It seems the dtor/finalizer should only be called when the ctor
has been run successfully.

It is definitely a bug, and fixing it properly will probably require changes to
D runtime and the compiler.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
May 02 2010