It looks like there is a fairly severe memory leak in the channel.cs file of the C# libiio binding code. The following code pins an array for use over the managed/native interop interface using GCHandle.Alloc(). However, GCHandle.Free() is never used to unpin the array, so each call the read() or write() causes the allocated array to stay pinned in memory and the .Net garbage collector cannot clean it up. For large acquisitions, the amount of memory leaked is substantial (i.e. gigabytes).
public byte[] read(IOBuffer buffer, bool raw = false) | |
{ | |
if (!is_enabled()) | |
throw new Exception("Channel must be enabled before the IOBuffer is instancied"); | |
if (is_output()) | |
throw new Exception("Unable to read from output channel"); |
byte[] array = new byte[(int) (buffer.get_samples_count() * sample_size)]; | |
MemoryStream stream = new MemoryStream(array, true); | |
IntPtr addr = GCHandle.Alloc(array, GCHandleType.Pinned).AddrOfPinnedObject(); | |
uint count; |
if (raw) | |
count = iio_channel_read_raw(this.chn, buffer.buf, addr, buffer.get_samples_count() * sample_size); | |
else | |
count = iio_channel_read(this.chn, buffer.buf, addr, buffer.get_samples_count() * sample_size); | |
stream.SetLength((long) count); | |
return stream.ToArray(); |
} |
public uint write(IOBuffer buffer, byte[] array, bool raw = false) | |
{ | |
if (!is_enabled()) | |
throw new Exception("Channel must be enabled before the IOBuffer is instancied"); | |
if (!is_output()) | |
throw new Exception("Unable to write to an input channel"); |
IntPtr addr = GCHandle.Alloc(array, GCHandleType.Pinned).AddrOfPinnedObject(); | |
if (raw) | |
return iio_channel_write_raw(this.chn, buffer.buf, addr, (uint) array.Length); | |
else | |
return iio_channel_write(this.chn, buffer.buf, addr, (uint) array.Length); | |
} |
Can we get this fixed?