VS2015断点调试神坑之为引用变量赋值为null不成功?

本文通过一个GIF演示了在使用Visual Studio进行调试时遇到的一个奇怪现象:已将成员变量赋值为null,但在调试过程中该变量仍保留值并发生变化。文章详细解析了这一现象背后的原因,即调试器为获取属性值自动创建了新实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先来看一个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后又有值了,有可能是某个变量突然莫名其妙的变化了等等。

如果以后发生了直接运行没什么问题,但是断掉调试的时候莫名其妙的情况,可以往这个方向上先考虑一下,排除是因为查看变量展开导致调用了属性的问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值