【问题标题】:Memory leaks Questions .net内存泄漏 Questions .net
【发布时间】:2012-02-19 04:24:40
【问题描述】:

我对编写代码的正确方法有点困惑。我读到我不必在变量中保留引用,因为垃圾收集不会清理它,但我不明白一些事情。

  1. 这段代码怎么样:

    private List<String> foo;
    
    public List<String> bar ()
    {
        foo = new List<String>();
        foo.add(something);
        return foo;
    }
    

每次我调用 bar 方法时 old foo list 丢失引用,它将成为垃圾收集的候选对象?我应该在类开始时声明(并初始化????)大部分变量并在方法开始后使用或声明之前并在方法内初始化?

2。 处置的对象呢?如果我写这段代码

private void browser_navigating(Object sender, NavigatingEventargs e)
{
    Uri someurl = new URI(something);
    List<String> somelist = new List<String>();
}

如果我有 20 个使用导航事件的 webBrowser 对象,它们会在导航事件触发时创建 Uri 和 List 对吗?但是当我处理 webBrowser 时,事件内部的对象会发生什么?他们会失去参考吗?当我处理一些适用于他所有孩子的东西时,它是否也适用于那些不实现 iDisposable(如 Uri 和 List)的对象,所以它们会从垃圾中清理掉还是留在内存中?

2.1。此事件在注册它的对象被释放后会自动取消注册?

3) 我读到静态对象是内存泄漏的问题。 如果我需要多次使用一个类,我是否应该每次都创建它,我需要将它声明为静态(例如,在我的情况下,我有一个静态连接类,它里面有登录和与网络服务器通信的方法,我声明静态的(在我的 mainWinform 类中),因为我将登录时收到的 cookie 存储在其中)

我会感谢你能回答我的问题。

【问题讨论】:

    标签: .net events memory memory-leaks


    【解决方案1】:

    每次我调用 bar 方法时,旧的 foo 列表都会丢失引用,它将成为垃圾收集的候选对象?

    这可能是真的。赋值foo = new List&lt;String&gt; 导致foo 停止指向先前的List&lt;string&gt; 值。如果foo 是该对象的only 引用,那么它将可用于收集。但是,如果您的类型中的另一个函数暴露了该对象,那么它可能仍然存在。例如

    List<string> GetFoo() {  
      return foo;
    }
    

    我读到静态对象是内存泄漏的问题

    这是部分正确的。当对象引用在不再被积极使用后被 GC 根持有时,.Net 中会发生内存泄漏。静态字段是 GC Root 并且是一种麻烦的方式,因为它不会像局部变量那样消失。静态字段本质上将对象永久保存在内存中。

    class Holder {
      public static List<string> StaticField;
    }
    
    Holder.StaticField = GetFoo();  
    

    最初存储在foo 中的List&lt;string&gt; 现在被StaticField 引用。在StaticField 指向另一个对象之前,它会将List&lt;string&gt; 保留在内存中以供程序的其余部分使用

    【讨论】:

      【解决方案2】:

      1:我应该在类开始时声明(并初始化???

      一般来说,一个对象在你完成它的那一刻就应该超出范围。因此,如果它只在方法内部使用,它应该是该方法的本地。对象的生存时间越长,它就越有可能被提升到堆上的更高一代。更高代的数据收集起来更昂贵,而且收集的频率要低得多。因此,尽快让对象超出范围通常会减少您的内存消耗并让您的程序运行得更快。

      2:但是当我处理 webBrowser 时,事件中的对象会发生什么?他们会失去参考吗?当我处理一些适用于他所有孩子的东西时,它是否也适用于那些不实现 iDisposable(如 Uri 和 List)的对象,所以它们会从垃圾中清理掉还是留在内存中?

      当你处理掉一个对象时,它实际上已经死了。任何其他拥有它引用的人仍然会拥有该引用,但如果他们尝试对它做任何事情,该对象将(或无论如何应该)引发ObjectDisposedException。

      对象的非托管资源(文件句柄、连接等)在释放后立即释放。它的非托管资源由垃圾收集器正常清理。因此,在对该对象的最后一个引用超出范围之前,它们不会被清理。

      3) 我读到静态对象是内存泄漏的问题。

      这是因为类的静态字段永远不会超出范围。因此,除非您明确将其引用设置为 null 或将其替换为其他内容,否则它们引用的任何数据都无法清理。

      最好单独处理与 Web 服务器的每个会话。这不仅有助于垃圾收集器在您之后进行清理,而且还使您能够执行诸如拥有多个并发会话之类的事情。

      【讨论】:

        猜你喜欢
        • 2011-03-22
        • 1970-01-01
        • 2022-12-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-11-21
        相关资源
        最近更新 更多