图说VS2019的一个必现崩溃(续)

    仍使用昨天的方法,重现问题,仍然是百发百中,而且仍然是崩溃到相同的地方,也就是System_Windows_Forms_ni模块的如下方法:

    System.Windows.Forms.PropertyGridInternal.PropertyGridView+GridViewEdit.ProcessDialogKey(System.Windows.Forms.Keys)

    .Net下的名字都很长,我们取ProcessDialogKey的首字母将其简称为PDK方法。

    从汇编角度看,崩溃在如下地址的MOV指令:

7b1a3ea3 8b01            mov     eax,dword ptr [ecx]  ds:002b:00000000=????????

    翻译为C/C++,这条指令相当于

    a = * this

    也就是使用指针的时候,指针的目标地址为空。

    使用SOS的ip2md命令可以找到这条指令的方法描述(MD)

0:000> !ip2md @eip

MethodDesc:   7a844330

    把MD的地址交给SOS的反汇编命令,可以得到这个方法的完整汇编清单。刚好一个屏幕可以显示到崩溃的位置。

640?wx_fmt=png

    感谢设计x86汇编的前辈们为我们贡献了如此通俗易懂的机器语言。

    注意崩溃点附近的指令,即:

7b1a3e96 ff15fc8d747a    call    dword ptr [System_Windows_Forms_ni+0x38dfc (7a748dfc)] (System.Windows.Forms.PropertyGridInternal.PropertyGridView.get_SelectedGridEntry(), mdToken: 06004edb)

7b1a3e9c 8bc8            mov     ecx,eax

7b1a3e9e ba05000000      mov     edx,5

7b1a3ea3 8b01            mov     eax,dword ptr [ecx]

    上面的call指令是调用get_SelectedGridEntry()方法,第二条是把返回值赋给ecx,接下来的edx = 5 暂时无关,而后便是崩溃的引用空指针指令。

    天啊,居然如此的没有任何悬念,如果用C++表示,那么上述指令相当于:

    pEntry = xxGridView.get_SelectedGridEntry();

    pEntry->xxxMethod();

    就是这样一次调用,没有判断返回值。

    尊敬的各位读者和同行们,这个错误是不是有点LOW呢?关于是否一定要判断返回值是有些灵活性的,但是这样的get_SelectedGridEntry太有可能返回空了吧,所以这里不加个判断,你说应该么?写到这里挺想把这个函数的实现和老版本比较一下,看看这个代码有多久了。按理说应该是不长时间的,不然这样的问题不知触发了多少个爆炸啊!

    且慢,我们还是拿出这个方法的完整IL看一下吧。还是一个屏幕刚好显示到崩溃的地方。   

640?wx_fmt=png

    截取崩溃点附近的IL:

IL_0040: ldarg.0 

IL_0041: ldfld GridViewEdit::psheet

IL_0046: callvirt System.Windows.Forms.PropertyGridInternal.Proper::get_SelectedGridEntry

IL_004b: callvirt System.Windows.Forms.PropertyGridInternal.GridEn::OnValueReturnKey

    两个callvirt连在一起,也是真真切切的没有判断返回值。

    

    看来问题很确定了,就是在这个PDK方法里,调用get_SelectedGridEntry获取选中项后,没有预料到它会返回空。

    

    不过,也有人可能会说,在编辑的情况下,get_SelectedGridEntry是不应该返回空的。

    在笔者试图跟踪get_SelectedGridEntry函数时,发现在出问题的0号线程中发生了一串异常:

(72a8.855c): C++ EH exception - code e06d7363 (first chance)

(72a8.855c): CLR exception - code e0434352 (first chance)

(72a8.855c): Unknown exception - code 000006ba (first chance)

    而且,在执行到上面分析的崩溃点之前,还发生了依次非法访问:

640?wx_fmt=png

    出问题的方法是:

System.Windows.Forms.PropertyGrid.OnPropertyValueSet

    执行经过是:

640?wx_fmt=png

    从前面的IL代码来看,PDK方法是先调用UnfocusSelection,再调用get_SelectedGridEntry和OnValueReturnKey,看来是调用UnfocusSelection时就埋下了隐患,导致后来的get_SelectedGridEntry返回空,这是可能的原因,不能是bug的理由(^_^)。

    上了调试器后,还发现,进程中有很多C++异常。

640?wx_fmt=png

    天啊,微软的工程师都不用WinDBG了么?

    开玩笑,当然不是,认识好几位WinDBG高手在微软工作呢。但是从今天观察到的现象来看,至少.Net团队的一些工程师不常用windbg啊。

   概而言之,问题还不只一个,只不过压死骆驼的最后一根稻草是没有判断get_SelectedGridEntry的返回值。

    

    上一篇文章发出后,不少朋友说微软已经很少有测试设计工程师(SDET)了。看来微软也是受“新测试方法论”影响的。看到其它很多公司没有专门的测试工程师,“我为什么不节约成本呢?”最近仔细学习了很多关于莱布尼茨的资料,现在不由得想起他说的一句话:不发生作用的东西是不会存在的。每个人都在影响别人,也在被影响。

    那么本文所讨论的如此明显的BUG是否与取消SDET有关呢?我认为是有的。至少测试的投入少了啊。《大学》里有句经典的话:“其所厚者薄,而其所薄者厚,未之有也”意思是说,如果在一件事用的功夫多,收获反而少;用的功夫少,收获反而多,这是从来没有过的。我们的前辈如此幽默,好美的回旋体。

    也有朋友说,现在是云时代了,所有用户都是测试团队,用不着自己花钱测试了。这就更值得思考了。退很多步说,至少对于微软这样的公司,对于Visual Studio这样的产品,有如此明显的BUG,还是不应该的,要口诛笔伐一下的。

    时代在变,软件也在变,哪些东西是该坚守的,哪些又是该让步的呢?“人生的境界在于高度,软件的境界在于深度”,深刻认识软件,严谨对待每一行代码是我们该坚守的。

    

640?wx_fmt=jpeg

(封面照片:2018年10月与格友们在庐山秀峰)

***********************************************************

正心诚意,格物致知,以人文情怀审视软件,以软件技术改变人生

欢迎访问http://001001.org/gedu/了解软件调试高级研习班的最新信息

或者关注格友公众号

640?wx_fmt=jpeg

   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值