【问题标题】:Memory leak analysis and help requested内存泄漏分析和帮助请求
【发布时间】:2019-05-16 00:27:04
【问题描述】:

我一直在使用 methodology outlined by Shivprasad Koirala 检查 C# 应用程序 (VoiceAttack) 中运行的代码是否存在内存泄漏。它基本上涉及使用性能监视器来跟踪应用程序的私有字节以及所有堆中的字节,并比较这些计数器以评估是否存在泄漏以及什么类型(托管/非托管)。理想情况下,我需要在 Visual Studio 之外进行测试,这就是我使用这种方法的原因。

以下代码部分生成以下内存配置文件(请记住,与 Visual Studio 相比,该代码的格式略有不同,因为这是包含在主 C# 应用程序中的函数):

public void main()
{
    string FilePath = null;
    using (FileDialog myFileDialog = new OpenFileDialog())
    {
        myFileDialog.Title = "this is the title";
        myFileDialog.FileName = "testFile.txt";
        myFileDialog.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
        myFileDialog.FilterIndex = 1;

        if (myFileDialog.ShowDialog() == DialogResult.OK)
        {
            FilePath = myFileDialog.FileName;
            var extension = Path.GetExtension(FilePath);
            var compareType = StringComparison.InvariantCultureIgnoreCase;
            if (extension.Equals(".txt", compareType) == false) 
            {
                FilePath = null;
                VA.WriteToLog("Selected file is not a text file. Action canceled."); 
            }
            else
                VA.WriteToLog(FilePath);
        }
        else 
            VA.WriteToLog("No file selected. Action canceled.");
    }
    VA.WriteToLog("done");
}

您可以看到,运行此代码后,私有字节数不会恢复到原始计数,并且所有堆中的字节数大致恒定,这意味着 有一部分未释放的非托管内存。连续几次运行相同的内联函数不会导致观察到的最大私有字节数或未释放内存进一步增加。一旦主 C# 应用程序 (VoiceAttack) 关闭,所有相关内存(包括上述代码的内存)都会被释放。坏消息是,在正常情况下,主应用程序可能会被用户无限期地运行,导致分配的内存保持未释放。

为了更好地衡量,我将相同的代码放入 VS(在 using 块之前和之后添加了一对 Thread.Sleep(5000) 以便更好地进行图形分析)并构建了一个可执行文件以使用性能监视器方法进行跟踪,结果是一样的。 OpenFileDialog 有一个初始的非托管内存跳转,分配的非托管内存永远不会回到原始值。

上述内存和泄漏跟踪方法是否有意义?如果是,有什么办法可以正确释放非托管内存?

【问题讨论】:

    标签: c# memory-leaks filedialog unmanaged-memory performance-monitor


    【解决方案1】:

    上述内存和泄漏跟踪方法有意义吗?

    没有。你不应该期望非托管的提交内存(私有字节)总是被释放。例如进程有一个非托管堆,它被管理以允许后续分配。由于 Windows 可以分页您提交的内存,因此最小化每个进程提交的内存并不重要。

    【讨论】:

    • 我认为 Private Bytes 是指为应用程序分配的总内存,而您将 Private Bytes 称为非托管已提交内存。它们是相同的还是我们混合使用的术语?
    • “Private Bytes”在这个上下文中与“Committed Memory”基本相同。
    • 好的,如果我理解正确,只要分配中没有增加,我就不应该担心私有字节的这种“指定用途”?
    • 正确。随着时间的推移持续增加是内存泄漏的标志。
    • 我正在做的大部分事情 (IMO) 不需要深入研究像 dotTrace 或 ANTS 这样复杂的东西,并且知道“是否存在泄漏”现在对我有好处。除了我认为应该始终完全释放非托管内存的错误假设之外,上述方法的其余部分是否仍然有效?
    【解决方案2】:

    如果重复调用不会增加内存使用量,则说明您没有内存泄漏,而是延迟了初始化。有些组件在您使用它们之前不会被初始化,因此在您建立基线时不会考虑它们的内存使用情况。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-28
      • 2012-09-25
      • 2011-02-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多