Doug Null
Doug Null

Reputation: 8327

GC not disposing multiple objects because each one references the previous object

EXPLANATION... GC doesn't dispose the objects because each one references the previous object.

My app inputs USB packets then, for each packet n, instantiates a class object that contains the packet n plus a reference to the previous object (packet n-1).

Each object n has member "dim previous_buffer as Antenna_Frame_Buffer_class" that references (ie. =) the previous object n-1, to facilitate thread coordination.

A thread is started for each object to process its packet data and then die (ie return).

PROBLEM - SEVER MEMORY LEAK.......... I’m getting a severe memory leak because GC fails to dispose of the objects because each object n has that member that references the previous packet object n-1. (The member type (‘as’) is the object’s class Antenna_Frame_Buffer_class.)

When I don’t set the previous_buffer member, GC disposes all buffers just fine.

I’ve tried setting the previous_buffer member to Nothing and also to a dummy buffer. But GC still doesn’t dispose.

How do I plug this leak??

THE CODE..................

        Public Class Antenna_Frame_Buffer_class
            public board_frame_array()          as Byte


            ' Link buffer and its thread to next buffer and thread:
                public previous_buffer          as Antenna_Frame_Buffer_class     ' Ref to previous contiguous buffer, for passing control of status update and graphing
                public status_file_control      as ManualResetEvent     ' Initially unsignalled, blocks the subsequent thread from status update

        End Class


        . . .

        ' MAIN LOOP...

        dim previous_buffer as antenna_frame_buffer_Class

        first_buffer = true
        do
           . . .

            ' Allocate memory for USB packet:
            antenna_frame_buffer.board_frame_array = New byte( std.frame_set_bytes - 1 ) {} 

           if first_buffer
            first_buffer = false
            else
            ' Init ref to previous (ie. n-1) buffer:
                antenna_frame_buffer.previous_buffer =  previous_buffer         ' AAAAAAAAAAAAAAAAAAAAAAAAA
            end if


            '  RECEIVE USB PACKET.
                          ...receive( antenna_frame_buffer.board_frame_array ... )

           buffer_thread = New Thread( AddressOf run_buffer_thread )

           buffer_thread.Start( antenna_frame_buffer)


           ' Reference to previous buffer
           previous_buffer =  antenna_frame_buffer

           . . .
        loop





        Sub run_buffer_thread( antenna_frame_buffer)

                ' Waits for signal from prev buffer thread:
                antenna_frame_buffer.previous_buffer.status_file_control.WaitOne()

            ' processes antenna_frame_buffer.board_frame_array
            . . .


            ' Signal next buffer thread to proceed:
            antenna_frame_buffer.status_file_control.Set()

            ' Thread now dies, bug GC never disposes of it if I have line AAAAAAAAAAAAAAAAAAAAAAAAA.
            ' If no line AAAAAAAAAAAAAAAAAAAAAAAAA then GC disposes each buffer just fine.
        End Sub

Upvotes: 0

Views: 47

Answers (1)

jmcilhinney
jmcilhinney

Reputation: 54417

I think that your terminology is a bit off. A memory leak is specifically when you can no longer access allocated memory in order to deallocate it. That will not be happening in your case. If you are still holding a reference to the last object in your code then you still have access to all the memory you allocated. If you're not then, at worst, the GC will take multiple cycles to clean up everything.

What you ought to do is implement IDisposable in your class and call Dispose on the last item. That Dispose method would call the Dispose method of the previous object and then set that field to Nothing. A single call to Dispose on the last object will then result in all objects decoupling.

This is why the IDisposable interface exists: to allow you to do explicit cleanup as soon as you're able, rather than waiting for the GC to finalise everything.

Upvotes: 1

Related Questions