Reputation: 8327
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
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