内存泄漏问题.net

时间:2012-01-25 23:28:11

标签: .net events memory memory-leaks

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

  1. 这段代码怎么样:

    private List<String> foo;
    
    public List<String> bar ()
    {
        foo = new List<String>();
        foo.add(something);
        return foo;
    }
    
  2. 每次我调用bar方法时, foo列表丢失引用并且它将成为垃圾收集的候选者?我应该在类的开头声明(并初始化???? )大部分变量并在之前使用或声明并在方法内初始化吗?

    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),那么他们是否会从Garbage清理它们还是会留在内存中?

    2.1。注册它的对象被处理后,这个事件会自动取消注册吗?

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

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

2 个答案:

答案 0 :(得分:1)

  

1:我应该在类的开头声明(并初始化????)大部分变量并使用after或之前声明并在方法内初始化吗?

一般情况下,对象一旦完成就应该超出范围。因此,如果它仅在方法中使用,则它应该是该方法的本地方法。对象存在的时间越长,就越有可能在堆上升级到更高的代。较高代的数据收集起来更昂贵,而且收集的频率要低得多。因此,尽快将对象从范围中移除通常会减少内存消耗,并使程序运行得更快。

  

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

当你处理一个物体时,它实际上已经死了。任何引用它的人仍然会有这个引用,但是如果对象尝试对它做任何事情,那么该对象将(或者应该)提出ObjectDisposedException

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

  

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

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

分别使用Web服务器处理每个会话要好得多。这不仅有助于垃圾收集器在您之后进行清理,而且还可以让您执行多个并发会话等操作。

答案 1 :(得分:0)

  

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

这可能是真的。作业foo = new List<String>会导致foo停止指向之前的List<string>值。如果foo是该对象的唯一引用,那么它将可用于收集。但是,如果您的类型中的另一个函数暴露了该对象,那么它可能仍然存在。例如

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

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

这是部分正确的。当GC根用户不再主动使用对象引用时,.Net中会发生内存泄漏。静态字段是GC根和一种麻烦的方式,因为它不像局部变量那样消失。静态字段基本上将对象永久保存在内存中。

class Holder {
  public static List<string> StaticField;
}

Holder.StaticField = GetFoo();  

最初存储在List<string>中的foo现在由StaticField引用。在StaticField指向另一个对象之前,它将List<string>保留在内存中以用于程序的其余部分