Archive

Archive for April 8th, 2005

Circular Relationships (VB6)

April 8th, 2005

While I’m thinking about VB6 (not something I’ve done for a while) I remembered another common problem relating to the fact VB is a reference counted language rather than a garbage collected one.

The Problem
For an object to be destroyed it’s reference count must reach zero, this is fine in the majority of cases because VB will happliy clean up references that are no longer in scope. However when a circular reference is created (i.e Parent->Child and Child->Parent) the reference count will never reach 0.

The Common Solution
Ensure all references are released (set to nothing in VB parlance) in the Terminate event of the classes in question. This works fine as long as your development team are incredibly dilligent. Of course in practice what happens is you create memory leaks which take ages to track down.

A Beter Solution
Make the Child->Parent relationship weak (i.e doesn’t increment the reference count on Parent). This can be accomplished with the following code (in a class)

Private Declare Sub CopyMemory Lib “kernel32″ Alias “RtlMoveMemory” (dest As Any, source As Any, ByVal bytes As Long)

Dim m_lParentPtr as Long

Public Property Set Parent(oParent as CParent)

    ’ ObjPtr is an undocumented function
    m_lParentPtr = ObjPtr(oParent)

End Property

Public Property Get Parent as CParent

    Dim oParent As CParent
    ’ Generate an object from the pointer
    CopyMemory oParent, m_lParentPtr, 4
    ’ Return it to the caller
    Set Parent = oParent
    ’ Kill the illegal reference(Your other option is to Increment the reference count on the illegal object to make it legal)
    CopyMemoryAny(WeakRef, 0&, 4&)
End Property

Private Sub IncrementRefCount
    ’ Increments reference counter (simulates IUnkown.AddRef)

    Dim lngRc As Long
    CopyMemory lngRc, ByVal (ObjPtr(Me)) + 4, 4 ‘ Get reference counter value…
    CopyMemory ByVal (ObjPtr(Me)) + 4, (lngRc + 1), 4 ‘ …and increment it

End Sub

Public Function RefCount As Long
    ’ returns the reference counter of obj

    Dim lngRc As Long
    CopyMemory lngRc, ByVal (ObjPtr(Me)) + 4, 4 ‘ Get reference counter…
    RefCount = lngRc - 2

End Function

PS: I haven’t checked this compiles because I don’t have a copy of VB6 handy but the important bits are correct…

/Technology

VB Speed

April 8th, 2005

I try to keep this quiet but I was a Visual Basic coder in a former life. I know lots of people consider VB to be a rubish language but you can do an awful lot with it if you push some of the boundaries. VBSpeed provides some excellent replacement functions for when you need to squeeze that exra ounce of performance (many of the VB6 string manipulation functions are pretty terrible).

/Technology