C#内存泄漏--event内存泄漏

论坛 期权论坛     
选择匿名的用户   2021-5-30 00:12   106   0
<div class="blogpost-body" id="cnblogs_post_body">
<blockquote>
  <p><span style="font-size:16px;">内存泄漏是指:当一块内存被分配后,被丢弃,没有任何实例指针指向这块内存, 并且这块内存不会被GC视为垃圾进行回收。这块内存会一直存在,直到程序退出。C#是托管型代码,其内存的分配和释放都是由CLR负责,当一块内存没有任何实例引用时,GC会负责将其回收。既然没有任何实例引用的内存会被GC回收,那么内存泄漏是如何发生的?</span></p>
</blockquote>
<ul><li><strong><span style="font-size:16px;">内存泄漏示例</span></strong></li></ul>
<p><span style="font-size:14px;">  为了演示内存泄漏是如何发生的,我们来看一段代码</span></p>
<div class="cnblogs_code">
  <pre class="blockcode"><span style="color:#0000ff;">class</span><span style="color:#000000;"> Program
{
    </span><span style="color:#0000ff;">static</span> <span style="color:#0000ff;">event</span><span style="color:#000000;"> Action TestEvent;
    </span><span style="color:#0000ff;">static</span> <span style="color:#0000ff;">void</span> Main(<span style="color:#0000ff;">string</span><span style="color:#000000;">[] args)
    {
        </span><span style="color:#0000ff;">var</span> memory &#61; <span style="color:#0000ff;">new</span><span style="color:#000000;"> TestAction();
        TestEvent </span>&#43;&#61;<span style="color:#000000;"> memory.Run;
        OnTestEvent();
        memory </span>&#61; <span style="color:#0000ff;">null</span><span style="color:#000000;">;
        </span><span style="color:#008000;">//</span><span style="color:#008000;">强制垃圾回收</span>
<span style="color:#000000;">        GC.Collect(GC.MaxGeneration);
        Console.WriteLine(</span><span style="color:#800000;">&#34;</span><span style="color:#800000;">GC.Collect</span><span style="color:#800000;">&#34;</span><span style="color:#000000;">);
        </span><span style="color:#008000;">//</span><span style="color:#008000;">测试是否回收成功</span>
<span style="color:#000000;">        OnTestEvent();
        Console.ReadLine();
    }
    </span><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> <span style="color:#0000ff;">void</span><span style="color:#000000;"> OnTestEvent() {
        </span><span style="color:#0000ff;">if</span> (TestEvent !&#61; <span style="color:#0000ff;">null</span><span style="color:#000000;">) TestEvent();
        </span><span style="color:#0000ff;">else</span> Console.WriteLine(<span style="color:#800000;">&#34;</span><span style="color:#800000;">Test Event is null</span><span style="color:#800000;">&#34;</span><span style="color:#000000;">);
    }

    </span><span style="color:#0000ff;">class</span><span style="color:#000000;"> TestAction
    {
        </span><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span><span style="color:#000000;"> Run() {
            Console.WriteLine(</span><span style="color:#800000;">&#34;</span><span style="color:#800000;">TestAction Run.</span><span style="color:#800000;">&#34;</span><span style="color:#000000;">);
        }
    }
}</span></pre>
</div>
<p>   该例子中,memory.run订阅了TestEvent事件,引发事件后,会在屏幕上看到 TestAction Run。当memory &#61;null 后,memory原来指向的内存就没有任何实例再引用该块内存了,这样的内存就是待回收的内存。GC.Collect(GC.MaxGeneration)语句会强制执行一次垃圾回收,再次引发事件,发现屏幕上还是会显示TestAction Run。该内存没有被GC回收,这就是内纯泄漏。这是由TestEvent&#43;&#61;memory.Run语句引起的,当GC.Collect执行的时候,当他看到该块内存还有TestEvent引用,就不会进行回收。但是该内存已经是“无法到达”的了,即无法调用该块内存,只有在引发事件的时候,才能执行该内存的Run方法。这显然不是我想要的效果,当memory &#61; null执行时,我希望该内存在GC执行时被回收,并且当TestEvent被引发时,Run方法不会执行,因为我已经把该内存“解放”了。</p>
<p>  这里有一个问题,就是C#中如何“释放”一块内存。像C和C&#43;&#43;这样的语言,内存的声明和释放都是开发人员负责的,一旦内存new了出来,就要delete,不然就会造成内存泄漏。这更灵活,也更麻烦,一不小心就会泄漏,忘记释放、线程异常而没有执行释放的代码...有手动分配内存的语言就有自动分配和释放的语言。最开始使用垃圾回收的语言是LISP,之后被用在Java和C#等托管语言中。像C#,CLR负责内存的释放,当程序执行一段时间后,CLR检测到垃圾内存已经值得进行一次垃圾回收时,会执行垃圾回收。至于如何判定一块内存是否为垃圾内存,比较著名的是计数法,即有一个实例引用了该内存后,就在该内存的计数上&#43;1,改实例取消了对该内存的引用,计数就-1,当计数为0时,就被
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP