VS2015断点调试神坑之为引用变量赋值为null不成功?
来源:互联网 发布:最好背单词软件 编辑:程序博客网 时间:2024/06/04 19:00
先来看一个gif:
什么情况?明明已经赋值把obj.m_pA赋值为null了,可是为什么单步调试后m_pA却依然有值,而且m_pA.nVal的值还从0变成了1?为了搞明白这个问题,我们先来看下DebugTest的结构:
class DebugTest { static int nCount = 0; public DebugTest() { m_pA = new A(); } public class A { public A() { nVal = DebugTest.nCount++; } int nVal; } public A m_pA; A AVal { get { if (null == m_pA) { m_pA = new A(); } return m_pA; } } }
可以看到,DebugTest中有一个类型为A的Public变量,有一个返回A的AVal属性,并且AVal这个属性并不是单纯的返回m_pA,他有多做一个m_pA为null的话,就创建一个A实例的判断。每创建一个A类对象,对象实例中的nVal值就加1。
聪明如你,可能看到这就领悟到了,难道是在把m_pA赋为null后,又自动创建了一个A对象?没错!但问题是在哪里,什么时候创建的呢?我们再看一张图就明白了:
原因就是:在执行obj.m_pA = null;这行代码前,变量查看窗口已经对obj实例进行了展开,执行完这行代码后会刷新变量查看窗口中的obj变量,由于它是展开的,所以为了知道AVal的值,VS内部就执行了一遍AVal,然后根据AVal的逻辑,m_pA为空,于是创建了一个新的A类实例赋值给m_pA变量,在新的实例构造的时候,把最新的DebugTest.nCount 值1赋给了A.nVal。这也就解释了我们一开始看到的gif图中奇怪的现象。
其实到这边都还算好理解,坑的是,在新的A类对象构造的时候,既在A的构造函数段不到点(可能是出于如果段到了点,堆栈怎么显示的问题?),也没有任何的提示。所以如果你不知道这个坑又刚好不幸中招的话,那么你在断掉调试的时候可能就会发生很多完全理解的问题,这得取决于你在查看变量的展开类的属性中做了什么事。有可能是引用赋值为null后又有值了,有可能是某个变量突然莫名其妙的变化了等等。
如果以后发生了直接运行没什么问题,但是断掉调试的时候莫名其妙的情况,可以往这个方向上先考虑一下,排除是因为查看变量展开导致调用了属性的问题。
- VS2015断点调试神坑之为引用变量赋值为null不成功?
- 引用类型赋值为null与加速垃圾回收
- 通过引用的方式为对象变量赋值
- 【断点调试】VS2010为例
- ios项目中给变量赋值后,变量为null的情况
- 引用为变量
- VS2015断点调试快捷键
- C++之拷贝构造、赋值构造必须为引用?
- 改善C#程序的建议5:引用类型赋值为null与加速垃圾回收
- 改善C#程序的建议5:引用类型赋值为null与加速垃圾回收
- 建议53:必要时应将不再使用的对象引用赋值为null
- 改善C#程序的建议5:引用类型赋值为null与加速垃圾回收
- 声明一个变量为null
- 是否有必要显式的在方法体内将局部变量赋值为null
- 指针赋值为NULL;是什么意思呢?
- C#中‘事件’可否赋值为null
- delete指针以后应赋值为NULL
- bool? 什么意思 bool? isTrue;表示 bool isTrue = null ; 定义并给变量赋值为null;
- 设以带头结点的双向循环链表表示的线性表L=(a1,a2,……,an)。
- MongoDB,分组,聚合
- 青春的痛苦
- project euler 19 Counting Sundays
- 以一种极其优雅的方式来调用Toast和Snackbar
- VS2015断点调试神坑之为引用变量赋值为null不成功?
- 九个绝招,让你戒掉旧情人
- 晓之以理,不如动之以情——新书《以大致胜》解读(下篇)
- 使用Scala 读写MySQL 数据给Spark任务执行
- bzoj 3725: PA2014 Final Matryca 乱搞
- 【第二期免费送书】中奖名单
- opencv在ios上的简单实现[objective-c&c++]
- 机器学习(32)之典型相关性分析(CCA)详解 【文末有福利......】
- JQuery 加法计算器