【发布时间】:2013-03-28 21:04:31
【问题描述】:
我已经追踪了很远的泄漏,但我自己似乎无法理解(修复)它。我首先使用 ANTS 内存分析器来确保我的代码实际上是在堆叠内存。它从使用 25 MB 开始,但在一个小时左右的时间内使用超过 100 MB。我正在为其编写此代码的朋友实际上一直在使用这个有问题的程序,他用了整个 18 GB 的内存并得到了内存不足的异常。
泄漏部分对程序来说并不重要,但如果没有 RefreshSessions() 方法,它几乎没有用处。
我一直在从 Code Project 扩展项目 Vista Core Audio API Master Volume Control。
这是似乎泄漏的部分。不使用经过测试,不泄漏。
更新:
public void RefreshSessions()
{
Marshal.ThrowExceptionForHR(_AudioSessionManager.GetSessionEnumerator(out _SessionEnum));
_Sessions.Refresh(_SessionEnum);
}
(从这里删除了类代码)
我没有写太多代码,所以我可能遗漏了一些东西,但如果需要更多详细信息,您可以实际下载源代码,或者我可以尽我所能回答。
(此处删除了不必要的代码)
使用这个简单的控制台应用程序测试了泄漏:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
MMDeviceEnumerator DevEnum = new MMDeviceEnumerator();
MMDevice device = DevEnum.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia);
Console.ReadKey();
int i = 0;
while (i < 10000)
{
device.AudioSessionManager.RefreshSessions();
i++;
}
Console.ReadKey();
}
}
}
更新 2
我想我已经解决了。必须运行一些更长的测试,但至少看起来内存使用情况已经稳定。这个想法来自 dialer,他找到了 C++ 泄漏的修复方法。
public void RefreshSessions()
{
_Sessions.Release(); //added this
IAudioSessionEnumerator _SessionEnum;
Marshal.ThrowExceptionForHR(_AudioSessionManager.GetSessionEnumerator(out _SessionEnum));
_Sessions.Refresh(_SessionEnum);
}
这是SessionCollection中的部分:
public void Release()
{
Marshal.ReleaseComObject(_AudioSessionEnumerator);
}
这并不完全是建议的代码拨号器(我最终还是使用了它),但仍然如此。 正如他所说,这可能不是实现这一目标的最佳方式,但我会继续使用它,因为它似乎对我的应用程序没有任何不利影响。
【问题讨论】:
-
我没有看到
SessionoCollection类的代码,但是当你调用RefreshSessions方法时,会创建一个新的SessionCollection对象,但是_Sessions之前的值可能需要一些释放/处置代码的附加资源。您还创建了一个会话枚举器对象,因此请确保它也被正确处理。 -
不幸的是我的电脑坏了,甚至无法尝试太多。你的建议可能来自我给出的描述,但我无法解决问题。我已经能够更准确地指出它,但起源在代码的 COM 部分。我只是在尝试解决这个问题时才了解 COM,所以我在这方面的技能很弱。
-
您是否尝试构建一个包含此版本的
RefreshSessions()的最小可执行应用程序,该应用程序使用具有几千次迭代的循环来演示泄漏? -
现在做。制作了一个小型控制台应用程序,它只创建
MMDevice等待按下一个键(这样我就可以看到它使用了多少内存)然后调用RefreshSessions()1000 次并再次等待。内存消耗从 19 056K 上升到 23 680K 并保持不变。 10000 次迭代将其提升到 60 072K。 -
@Degath 您可以将应用程序的代码添加到问题中吗?
标签: c# memory-leaks unmanaged