【问题标题】:How to monitor Memory Leak in C#?如何监控 C# 中的内存泄漏?
【发布时间】:2013-05-01 16:35:28
【问题描述】:

我正在尝试做 Visual C# 的内存泄漏。我使用了这个代码:

class Program
{
    static void Main(string[] args)
    {
        List<float> s = new List<float>();
        while (true) {
            s.Add(10 ^ 10);
        }
    }
}

我运行了这个程序,在 2 分钟内,我得到了 OutofMemory 异常。这是内存泄漏的真实代码吗?我正在监视主内存空间,它有足够的空间。如果这是内存泄漏,那么即使 ram 中有空间,这也会导致这个内存泄漏?如何监控此泄漏?

【问题讨论】:

  • 您误解了内存泄漏和内存不足。内存不足可能是内存泄漏的症状,但它们并不是一回事。我建议您阅读两者,以便您了解其中的区别。
  • 以上评论 100% 正确。这是一种创建内存不足场景的方法

标签: c# memory-leaks out-of-memory


【解决方案1】:

这不是内存泄漏。您添加的每个号码仍然可以从您的列表对象中访问。你的代码只是使用了大量的内存,最终你用完了。

您可能正在点击the maximum amount of memory for a single object

垃圾收集器将确保与对象关联的内存在不再引用该对象时被释放。

【讨论】:

    【解决方案2】:

    您的示例不是内存泄漏,您将耗尽内存,但您创建的所有对象都可以被正在运行的程序访问。泄漏是指内存中有无法访问的对象。下面是 .NET 中最常见的泄漏原因示例,订阅静态事件:

    internal class Program
    {
        public static event EventHandler SomeStaticEvent;
    
        private static void Main()
        {
            while (true)
            {
                var a = new A();                
    
                //here a goes out of scope but won't be collected by GC because Program still holds reference to "a" by a static event subsription
            }
        }      
        public class A
        {                       
            public A()
            {
                //if you comment this line, there is no reference from Program to A and a will be GC-ed and memory allocated will be released
                Program.SomeStaticEvent+=ProgramOnSomeStaticEvent;
            }
            private void ProgramOnSomeStaticEvent(object sender, EventArgs eventArg){}
        }
    
    }
    

    订阅静态事件或长期对象的事件时要小心。您的程序正在泄漏,并且不容易发现原因。始终在对象超出范围之前取消订阅此类事件。

    【讨论】:

    • 从技术上讲,这也不是泄漏。你可以写一些代码来做:SomeStaticEvent = null 从而允许所有A 对象被释放。
    • 是的,你可以,但如果你不这样做怎么办。您可以(并且应该)取消订阅 aviod leak.. 正如我所见,当您没有做您应该做的事情时,它总是会发生泄漏?
    • 按照这个定义,OP 的代码确实是一个泄漏,因为如果他做了什么,内存可以被回收。有些人选择使用该定义(尤其是在 C# 中),如果他们清楚的话,这是可以的,但是使用该定义,您的代码与 OP 的代码没有什么不同。然而,在 C/C++ 中,当您丢失了对对象的所有引用但没有回收它的内存时,称为内存泄漏。发生这种情况时,您将失去回收它的能力。
    • 我明白你的意思,我同意。但C++不同,你必须调用析构函数,程序员负责内存释放。在 .NET 中,我们确实有 GC。这可能不是“真正的”泄漏,但根据我的经验,这是将“超出范围”对象留在内存中的非常常见的情况。我在很多库中都看到了这个“bug”,甚至是那些最有经验的团队创建的库。不管它是否泄漏,你丢失了内存并且如果没有一些你不应该做的黑客攻击就无法回收它。
    • 感谢大家的回复。我在 C/C++ 中尝试了带有指针示例的代码,并且我也在 C# 中尝试过。不知道在哪里,我发现错误。我一直在关注内存性能,但这对我来说似乎还不错。如果内存泄漏意味着程序没有释放它们的对象空间,那么我的程序也在做同样的事情。我发现,无论我添加什么,错误都会发生在相同的列表计数 xxxxxxxxx(9 位)计数。
    【解决方案3】:

    您希望s.Add 做什么?每次执行时,它都会在您的列表中添加一个新元素。所以第一次,你会有一个包含一个元素的列表,第二次s 现在是一个包含两个元素的列表,第 100 万次它会有一百万个元素。它会一直这样下去,直到它太大而无法放入内存。

    【讨论】:

    • 是的,你说得对。我想让我的内存满,直到我有内存泄漏。事实上,这正是我所期待的。但它没有发生。看来,我仍然有记忆,但 .NET 停止在 List 中添加更多元素。列表计数到 9 位数。
    猜你喜欢
    • 2021-12-25
    • 1970-01-01
    • 1970-01-01
    • 2019-09-26
    • 2010-12-20
    • 2010-10-11
    • 1970-01-01
    • 2016-01-27
    • 2010-11-11
    相关资源
    最近更新 更多