I use NAudio in my project, and i found maybe there is a memory leak in the following code.
```
public static IList<MixerControl> GetMixerControls(IntPtr mixerHandle, MixerLine mixerLine, MixerFlags mixerHandleType)
{
List<MixerControl> controls = new List<MixerControl>();
if (mixerLine.ControlsCount > 0)
{
int mixerControlSize = Marshal.SizeOf(typeof(MixerInterop.MIXERCONTROL));
MixerInterop.MIXERLINECONTROLS mlc = default(MixerInterop.MIXERLINECONTROLS);
IntPtr pmc = Marshal.AllocHGlobal(mixerControlSize * mixerLine.ControlsCount);
mlc.cbStruct = Marshal.SizeOf(mlc);
mlc.dwLineID = mixerLine.LineId;
mlc.cControls = mixerLine.ControlsCount;
mlc.pamxctrl = pmc;
mlc.cbmxctrl = Marshal.SizeOf(typeof(MixerInterop.MIXERCONTROL));
MmResult err = MixerInterop.mixerGetLineControls(mixerHandle, ref mlc, mixerHandleType);
if (err != MmResult.NoError)
{
Marshal.FreeHGlobal(pmc);
throw new MmException(err, "mixerGetLineControls");
}
for (int i = 0; i < mlc.cControls; i++)
{
long address = pmc.ToInt64() + (long)(mixerControlSize * i);
MixerInterop.MIXERCONTROL mc = (MixerInterop.MIXERCONTROL)Marshal.PtrToStructure((IntPtr)address, typeof(MixerInterop.MIXERCONTROL));
MixerControl mixerControl = MixerControl.GetMixerControl(mixerHandle, mixerLine.LineId, mc.dwControlID, mixerLine.Channels, mixerHandleType);
controls.Add(mixerControl);
}
}
return controls;
}
```
In the code above, it uses Marshal.AllocHGlobal to allocate memory for pmc, but when the function returns, the Marshal.FreeHGlobal is not called.
I think we can improve the code as below:
```
public static IList<MixerControl> GetMixerControls(IntPtr mixerHandle, MixerLine mixerLine, MixerFlags mixerHandleType)
{
List<MixerControl> controls = new List<MixerControl>();
if (mixerLine.ControlsCount > 0)
{
int mixerControlSize = Marshal.SizeOf(typeof(MixerInterop.MIXERCONTROL));
MixerInterop.MIXERLINECONTROLS mlc = default(MixerInterop.MIXERLINECONTROLS);
IntPtr pmc = Marshal.AllocHGlobal(mixerControlSize * mixerLine.ControlsCount);
mlc.cbStruct = Marshal.SizeOf(mlc);
mlc.dwLineID = mixerLine.LineId;
mlc.cControls = mixerLine.ControlsCount;
mlc.pamxctrl = pmc;
mlc.cbmxctrl = Marshal.SizeOf(typeof(MixerInterop.MIXERCONTROL));
MmResult err = MixerInterop.mixerGetLineControls(mixerHandle, ref mlc, mixerHandleType);
if (err != MmResult.NoError)
{
Marshal.FreeHGlobal(pmc);
throw new MmException(err, "mixerGetLineControls");
}
for (int i = 0; i < mlc.cControls; i++)
{
long address = pmc.ToInt64() + (long)(mixerControlSize * i);
MixerInterop.MIXERCONTROL mc = (MixerInterop.MIXERCONTROL)Marshal.PtrToStructure((IntPtr)address, typeof(MixerInterop.MIXERCONTROL));
MixerControl mixerControl = MixerControl.GetMixerControl(mixerHandle, mixerLine.LineId, mc.dwControlID, mixerLine.Channels, mixerHandleType);
controls.Add(mixerControl);
}
Marshal.FreeHGlobal(pmc);
}
return controls;
}
```
```
public static IList<MixerControl> GetMixerControls(IntPtr mixerHandle, MixerLine mixerLine, MixerFlags mixerHandleType)
{
List<MixerControl> controls = new List<MixerControl>();
if (mixerLine.ControlsCount > 0)
{
int mixerControlSize = Marshal.SizeOf(typeof(MixerInterop.MIXERCONTROL));
MixerInterop.MIXERLINECONTROLS mlc = default(MixerInterop.MIXERLINECONTROLS);
IntPtr pmc = Marshal.AllocHGlobal(mixerControlSize * mixerLine.ControlsCount);
mlc.cbStruct = Marshal.SizeOf(mlc);
mlc.dwLineID = mixerLine.LineId;
mlc.cControls = mixerLine.ControlsCount;
mlc.pamxctrl = pmc;
mlc.cbmxctrl = Marshal.SizeOf(typeof(MixerInterop.MIXERCONTROL));
MmResult err = MixerInterop.mixerGetLineControls(mixerHandle, ref mlc, mixerHandleType);
if (err != MmResult.NoError)
{
Marshal.FreeHGlobal(pmc);
throw new MmException(err, "mixerGetLineControls");
}
for (int i = 0; i < mlc.cControls; i++)
{
long address = pmc.ToInt64() + (long)(mixerControlSize * i);
MixerInterop.MIXERCONTROL mc = (MixerInterop.MIXERCONTROL)Marshal.PtrToStructure((IntPtr)address, typeof(MixerInterop.MIXERCONTROL));
MixerControl mixerControl = MixerControl.GetMixerControl(mixerHandle, mixerLine.LineId, mc.dwControlID, mixerLine.Channels, mixerHandleType);
controls.Add(mixerControl);
}
}
return controls;
}
```
In the code above, it uses Marshal.AllocHGlobal to allocate memory for pmc, but when the function returns, the Marshal.FreeHGlobal is not called.
I think we can improve the code as below:
```
public static IList<MixerControl> GetMixerControls(IntPtr mixerHandle, MixerLine mixerLine, MixerFlags mixerHandleType)
{
List<MixerControl> controls = new List<MixerControl>();
if (mixerLine.ControlsCount > 0)
{
int mixerControlSize = Marshal.SizeOf(typeof(MixerInterop.MIXERCONTROL));
MixerInterop.MIXERLINECONTROLS mlc = default(MixerInterop.MIXERLINECONTROLS);
IntPtr pmc = Marshal.AllocHGlobal(mixerControlSize * mixerLine.ControlsCount);
mlc.cbStruct = Marshal.SizeOf(mlc);
mlc.dwLineID = mixerLine.LineId;
mlc.cControls = mixerLine.ControlsCount;
mlc.pamxctrl = pmc;
mlc.cbmxctrl = Marshal.SizeOf(typeof(MixerInterop.MIXERCONTROL));
MmResult err = MixerInterop.mixerGetLineControls(mixerHandle, ref mlc, mixerHandleType);
if (err != MmResult.NoError)
{
Marshal.FreeHGlobal(pmc);
throw new MmException(err, "mixerGetLineControls");
}
for (int i = 0; i < mlc.cControls; i++)
{
long address = pmc.ToInt64() + (long)(mixerControlSize * i);
MixerInterop.MIXERCONTROL mc = (MixerInterop.MIXERCONTROL)Marshal.PtrToStructure((IntPtr)address, typeof(MixerInterop.MIXERCONTROL));
MixerControl mixerControl = MixerControl.GetMixerControl(mixerHandle, mixerLine.LineId, mc.dwControlID, mixerLine.Channels, mixerHandleType);
controls.Add(mixerControl);
}
Marshal.FreeHGlobal(pmc);
}
return controls;
}
```