为了账号安全,请及时绑定邮箱和手机立即绑定

C#中的内存泄漏

C#中的内存泄漏

慕尼黑的夜晚无繁华 2019-12-16 10:40:31
C#中的内存泄漏当您确保所有句柄和实现的对象IDispose都已处置时,在受管系统中是否有可能泄漏内存?在某些情况下会遗漏一些变量吗?
查看完整描述

4 回答

?
杨__羊羊

TA贡献1943条经验 获得超7个赞

事件处理程序是非常明显的内存泄漏的常见来源。如果您从object2订阅了object1上的事件,则执行object2.Dispose()并假装该事件不存在(并从代码中删除所有引用),则object1的事件中存在一个隐式引用,这将阻止object2被垃圾收集。


MyType object2 = new MyType();


// ...

object1.SomeEvent += object2.myEventHandler;

// ...


// Should call this

// object1.SomeEvent -= object2.myEventHandler;


object2.Dispose();

这是泄漏的常见情况-忘记轻松取消订阅事件。当然,如果收集了object1,则也将收集object2,但要到那时为止。


查看完整回答
反对 回复 2019-12-16
?
慕码人8056858

TA贡献1803条经验 获得超6个赞

我认为C ++风格的内存泄漏是不可能的。垃圾收集器应解决这些问题。即使不再使用这些对象,也可以创建一个聚合对象引用的静态对象。像这样:


public static class SomethingFactory

{

    private static List<Something> listOfSomethings = new List<Something>();


    public static Something CreateSomething()

    {

        var something = new Something();

        listOfSomethings.Add(something);

        return something;

    }

}

那显然是一个愚蠢的例子,但这等同于托管运行时内存泄漏。


查看完整回答
反对 回复 2019-12-16
?
慕慕森

TA贡献1856条经验 获得超17个赞

正如其他人指出的那样,只要在内存管理器中没有实际的错误,不使用非托管资源的类就不会泄漏内存。


在.NET中看到的不是内存泄漏,而是永不处置的对象。只要垃圾收集器可以在对象图上找到对象,该对象就不会被处置。因此,如果任何活动对象在任何地方都具有对该对象的引用,则该对象不会被丢弃。


事件注册是实现此目标的好方法。如果一个对象注册了一个事件,则无论它注册了什么对象,都具有对该事件的引用,并且即使您消除了对该对象的所有其他引用,直到该对象取消注册(或与其注册的对象变得不可访问),它仍将保持活动状态。


因此,您必须注意在不知情的情况下注册静态事件的对象。ToolStrip例如,的一个漂亮功能是,如果您更改显示主题,它将自动在新主题中显示。它通过注册静态SystemEvents.UserPreferenceChanged事件来实现此精美功能。更改Windows主题时,将引发该事件,并且ToolStrip正在监听该事件的所有对象都将收到一个新主题的通知。


好的,假设您决定放弃ToolStrip表格上的:


private void DiscardMyToolstrip()

{

    Controls.Remove("MyToolStrip");

}

您现在拥有一个ToolStrip永不消逝的世界。即使它不再存在于您的表单中,每次用户更改主题时,Windows都会忠实地告知ToolStrip有关此主题的信息。每当垃圾收集器运行时,它都会认为“我不能扔掉该对象,UserPreferenceChanged事件正在使用它。”


那不是内存泄漏。但也可能如此。


这样的事情使内存分析器变得无价。运行一个内存分析器,您会说:“很奇怪ToolStrip,即使我的表单上只有一个对象,堆上似乎有一万个对象。这是怎么发生的?”


哦,如果您想知道为什么有些人认为属性设置者是邪恶的:ToolStrip要从UserPreferenceChanged事件中取消注册,请将其Visible属性设置为false。


查看完整回答
反对 回复 2019-12-16
  • 4 回答
  • 0 关注
  • 1080 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信