一直想做这么一个测试,人和手的测试。类型"人"有一个属性"手",需要"手"也可以读取"人"的数据。则"手"下面也有一个属性"人"。

如果用代码表现,则是:

public class Class人
{
private Class手 _手;
public Class手 手 { get { return _手; } set { _手 = value; } } private Class脚 _脚;
public Class脚 脚 { get { return _脚; } set { _脚 = value; } } private Class脑 _脑;
public Class脑 脑 { get { return _脑; } set { _脑 = value; } } public Class人()
{
_手 = new Class手(this);
_脚 = new Class脚(this);
_脑 = new Class脑(this);
}
} public class Class手
{
private Class人 _人;
public Class人 人 { get { return _人; } } public Class手(Class人 one)
{
_人 = one;
}
}

这样可以实现 人.手 和 手.人 的相互访问。

我的疑问是:人和手之间的这种相互强引用会不会造成资源一直处于被引用状态,不能被回收,从而导致内存泄漏?

于是做了一个测试,测试的思路是:建立两个相互引用的类A/B,其中A含有B,B只需要访问A。A构造的时候会占用大量的内存。执行的时候,在函数以外定义变量C来承装List<A>并初始化。在函数内,重复的生成A的实例并放到C中。在某个时段,将C清空,强制垃圾回收,看A的集合占用的内存是否会释放。代码如下:

public class Class人
{
private Class手 _手;
public Class手 手 { get { return _手; } set { _手 = value; } }
public List<string> Data;
public Class人()
{
_手 = new Class手(this);
Data = new List<string>();
for (int i = ; i < ; i++)
Data.Add(Enumerable.Range(, ).Select(x => x.ToString()).Aggregate((x, y) => x + y));
}
} public class Class手
{
private Class人 _人;
public Class人 人 { get { return _人; } } public Class手(Class人 one)
{
_人 = one;
}
}

执行代码:

static List<Class人> data = new List<Class人>();
static void Main(string[] args)
{
for (int i = ; i < ; i++)
data.Add(new Class人()); Console.WriteLine("ok");
var read = Console.ReadLine();
if (read == "Y")
{
data.Clear();
GC.Collect();
} Console.ReadKey();
}

测试的结果如下:

1. 在启动程序前,内存占用61%;

2. 启动后,"ok"前,也就是生成Class人的实例集合后,内存占用68%。

3.1 如果此时输入"Y",立刻清空承载的data变量,并进行垃圾回收,内存占用返回至62%,关闭程序后返回61%。

3.2  如果此时输入"Y",只是清空data,不执行垃圾回收,内存还停留在68%,关闭程序后直接返回61%(参考3.1,等到下一个垃圾回收时,应该会清空至62%)

由此可以推出,即使数据里面,class人和class手相互引用了,但没有其他数据调用时,垃圾回收机制仍然会将其视为垃圾然后回收。

本来想通过弱引用处理这种相互引用的,通过测试后,感觉不用。以下贴出我查询到的一些声音:

".NET不是使用引用计数器的方法"

".NET处理循环引用不是通过弱引用来实现的,而是通过遍历对象,释放无法访问的对象来完成的"

由于对.net的垃圾回收机制研究得不通透,所以给不了一些原理上的解释,如果有大牛知道这一部分,欢迎给我留言。

如果测试结果有误,请严肃纠正。

转载请注明出处:http://www.cnblogs.com/icyJ

.net 循环引用是否会造成内存泄漏的更多相关文章

  1. 讲述Sagit.Framework解决:双向引用导致的IOS内存泄漏(中)- IOS不为人知的Bug

    前言: 话说昨晚还是前晚,写了一篇:讲述Sagit.Framework解决:双向引用导致的IOS内存泄漏(上) 文章写到最后时,多了很多莫名奇妙的问题!!! 为了解决了这些莫名奇妙的问题,我又战斗了2 ...

  2. 讲述Sagit.Framework解决:双向引用导致的IOS内存泄漏(下)- block中任性用self

    前言: 在处理完框架内存泄漏的问题后,见上篇:讲述Sagit.Framework解决:双向引用导致的IOS内存泄漏(中)- IOS不为人知的Bug 发现业务代码有一个地方的内存没释放,原因很也简单: ...

  3. [转] weak_ptr解决shared_ptr环状引用所引起的内存泄漏

    http://blog.csdn.net/liuzhi1218/article/details/6993135 循环引用: 引用计数是一种便利的内存管理机制,但它有一个很大的缺点,那就是不能管理循环引 ...

  4. weak_ptr解决shared_ptr环状引用所引起的内存泄漏[转]

    转载:http://blog.csdn.net/liuzhi1218/article/details/6993135 循环引用: 引用计数是一种便利的内存管理机制,但它有一个很大的缺点,那就是不能管理 ...

  5. echarts配合循环计时器等出现的内存泄漏

    echarts是百度的一个图表插件,确实好用美观. 之前实习接触到的页面大多是下面这种调用方式 var chart=echarts.init(document.getElementById(dom)) ...

  6. 讲述Sagit.Framework解决:双向引用导致的IOS内存泄漏(上)

    前言: 好久没写文章了,最近先是重构IT恋.又重写IT恋中. Sagit框架也不断的更新,调整,现在感觉已完美了了相当的多. 今天不写教程,先简单分享一下技术内容. 1:见Block必有:#defin ...

  7. JavaScript的闭包和内存泄漏问题

    闭包 http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html JavaScript中必须提到的功能最强大的抽象 ...

  8. JavaScript 中的内存泄漏

    JavaScript 中的内存泄漏 JavaScript 是一种垃圾收集式语言,这就是说,内存是根据对象的创建分配给该对象的,并会在没有对该对象的引用时由浏览器收回.JavaScript 的垃圾收集机 ...

  9. <转>Python的内存泄漏及gc模块的使用分析

    一般来说在 Python 中,为了解决内存泄漏问题,采用了对象引用计数,并基于引用计数实现自动垃圾回收.由于Python 有了自动垃圾回收功能,就造成了不少初学者误认为自己从此过上了好日子,不必再受内 ...

随机推荐

  1. Linux 4.10中两个新特性与我的一段故事

    今早5点半起来没有開始写文章,而是去西湾红树林连跑带走折腾了将近20公里.回来后就8点多了...洗了个澡之后坐稳当.開始写一段关于我的故事.        在2014年到2015年期间,我在负责研发一 ...

  2. stm8 io口重映射

    STM8S003F3端口可以设置重映射,如pin16的PC6管脚,默认复用功能是SPI_MOSI功能,可以重映射为TIM1_CH1,也就是timer1的1通道.映射方式并不像STM32那样有个AFR寄 ...

  3. [转]FutureTask详解

     FutureTask类是Future 的一个实现,并实现了Runnable,所以可通过Excutor(线程池) 来执行,也可传递给Thread对象执行.如果在主线程中需要执行比较耗时的操作时,但又不 ...

  4. C#基础第八天-作业答案-设计类-面向对象方式实现两个帐户之间转账

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  5. nginx 反向代理说明

    1 在大型项目开发中,可能会有多个应用部署在不同机器上,如果想让用户访问单个域名或IP访问到这些应用,可以使用 nginx 的反向代理,将应用的地址通过 nginx 代理,用户通过访问 nginx 地 ...

  6. 微信小程序图片宽100%显示并且不变形

    <view class="meiti" style="background-color:red;"> <image src="htt ...

  7. Java面试题(原创)

    1:int类型的范围值(可以用指数表示min--max) 答案:此题考对int占用的字节和计算机基础---2³¹-1到-2³¹ 2.java用来表示unicode的转义符是什么,并简要描述unicod ...

  8. Mac OSX 快捷键&命令行

    一.Mac OSX 快捷键 ctrl+shift                                    快速放大dock的图标会暂时放大,而如果你开启了dock放大Command+Op ...

  9. 认识和使用Task

    对于多线程,我们经常使用的是Thread.在我们了解Task之前,如果我们要使用多核的功能可能就会自己来开线程,然而这种线程模型在.net 4.0之后被一种称为基于“任务的编程模型”所冲击,因为tas ...

  10. win2008r2的iis7.5手动建站方法,iis7.5中用独立用户建立网站的方法,提高网站安全性

    win2003的iis6手动建站方法,iis6中用独立用户建立网站的方法,提高网站安全性,我们前面的教程有说明,请看http://www.piis.cn/zhishi/web574.asp 现在我们说 ...