[Issue 4092] New: broken memory management for COM objects derived from IUnknown

d-bugmail at puremagic.com d-bugmail at puremagic.com
Wed Apr 14 23:44:45 PDT 2010


http://d.puremagic.com/issues/show_bug.cgi?id=4092

           Summary: broken memory management for COM objects derived from
                    IUnknown
           Product: D
           Version: unspecified
          Platform: Other
        OS/Version: Windows
            Status: NEW
          Severity: normal
          Priority: P2
         Component: druntime
        AssignedTo: sean at invisibleduck.org
        ReportedBy: r.sagitario at gmx.de


--- Comment #0 from Rainer Schuetze <r.sagitario at gmx.de> 2010-04-14 23:44:39 PDT ---
Currently, instances of classes that derive from IUnknown are allocated from
the C-heap (see lifetime.d, function _d_newclass), but are never released in
the default implementation ComObject (see std.c.windows.com,
ComObject.Release()), because invariants might still be called.

In addition, ComObjects are not known to the garbage collector (which is
completely useless in at least 99% of all cases), so you have to override
ComObject's new to avoid a bad collection while executing the class
constructor.

I suggest allocating ComObjects from standard garbage collected objects, and
let the default imlpementation add ranges to the GC when AddRef is called with
reference count 0, and removing the range when Release is called:

class ComObject : IUnknown
{
    // [... QueryInterface ...]

    override ULONG AddRef()
    {
        LONG lRef = InterlockedIncrement(&count);
        if(lRef == 1)
        {
            uint sz = this.classinfo.init.length;
            GC.addRange(cast(void*) this, sz);
        }
        return lRef;
    }

    override ULONG Release()
    {
        LONG lRef = InterlockedDecrement(&count);
        if (lRef == 0)
        {
            GC.removeRange(cast(void*) this);
        }
        return cast(ULONG)lRef;
    }
}

Otherwise, the garbage collector is responsible of releasing memory. 

This also lets ComObject be handled like normal objects in D-Code (no need to
call AddRef/Release).

Here's the patch to lifetime.d:

Index: lifetime.d
===================================================================
--- lifetime.d    (revision 282)
+++ lifetime.d    (working copy)
@@ -98,7 +98,7 @@
     void* p;

     debug(PRINTF) printf("_d_newclass(ci = %p, %s)\n", ci, cast(char
*)ci.name);
-    if (ci.m_flags & 1) // if COM object
+    if (0 & ci.m_flags & 1) // if COM object
     {   /* COM objects are not garbage collected, they are reference counted
          * using AddRef() and Release().  They get free'd by C's free()
          * function called by Release() when Release()'s reference count goes

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


More information about the Digitalmars-d-bugs mailing list