开源代码分析技巧之——高效Windows源码分析

开源代码分析技巧之——高效Windows源码分析

       引言:项目开发中,我们免不了在已有代码或版本的基础上新增代码。这个时候,如何高效的读懂别人代码逻辑,如何从几十万乃至上百万行代码中找到自己需要的逻辑显得尤为重要。

       以下笔者结合自己的近来的经验就Windows源码分析做下解读。

一、了解Windows的代码特点

       相比于Linux源码,封装的特性在Windows下体现的尤为突出。尤其MFC下的程序开发,我们需要常备MSDN,了解函数接口的定义、返回值、参数(in或out)的含义。

       熟悉MFC的消息映射和传递机制。对于现成的实现,我们可参考使用不同的API,不必要重复造轮子。

二、通过文档了解代码实现

       项目中一般团队开发,对于已有的实现会有前期的需求分析文档、总体设计文档、详细或微型设计文档。对一个新人来讲,通过文档了解版本中已经实现的功能、采用的技术、实现的流程图等是很高效的方法。

       衡量你对实现功能了解的标准就是:你能给一个对该领域陌生的人讲解明白大致实现的原理。

三、自顶向下,分解开来

       虽然已有的代码量非常庞大,但对个人而言不可能面面俱到,我们往往是根据项目组的安排维护其中的一个或大或小的模块的代码量,在其中修改已有代码逻辑或新增新的功能。有了文档的大局观还需要自顶向下,将代码分解开来,直到细化到你所维护的代码的每一行。

       Windows下的自顶向下无非是:工程—>模块-->-->函数-->代码行

四、分析源码逻辑

        对于自己负责模块的功能实现,我们要了解新增功能的代码的添加位置?代码的前后逻辑及执行流程是怎么样的?新加后会不会对已有代码逻辑构成影响

        笔者案例:在代码中新增序列号未开启的功能,用于实现当客户购买设备当尚未购买该新增功能的序列号时是没有权限执行后续的操作的。这个时候就需要我负责的客户端的模块接收设备端的模块的反馈消息,并以弹窗的形式醒目的提示给客户。上面提到的添加位置、流程、构成影响三个问题便都出现。我的实现如下:

       第一步:充分跟读已有的代码逻辑,知道原有代码对初始登录出现错误(如网络异常)是如何提示用户的,大致确定添加的位置;

       第二步:考虑如何从对端(设备端)获取提示信息;

       第三步:在第一步的位置新增第二步获取的代码,并做不同场景下的测试,确保第一步位置的正确性以及新增代码逻辑不会对已有代码构成影响。

五、改动源码的前提是已经对已有逻辑了然如胸

       区别于以前自己写的小程序,代码逻辑简单、不与其他代码或逻辑关联,很容易定位出错原因。实际项目开发中大家团队作战、各司其职。修改一处的代码有可能“牵一发而动全身”。并且代码bug出现有的是必现的,有的和环境、场景有关为非必现的。非必现bug很难排查。

       笔者案例:在开发中笔者需要动态加载DLL,以调用其中提供的函数接口。笔者想当然以为,动态加载只要加上DLL的路径就没有问题。当时本机调试也没有问题,但经理说要在虚拟机看下执行效果时,将Release版本可执行程序拷贝过去至虚拟机后,发现根本不能执行。即:在本机执行没有任何bug,为什么换台机器后就不能执行了呢?这种问题是如何出现的以及如何调试解决的呢?(该问题正是一年前360面试官问过我的题目)。笔者排查如下:

       第一步:通读新增代码,看有没有逻辑bug。如果有修改之再测试;如果没有,则思考至第二步。

       第二步:为什么会换台机器就运行不了了?猜测多半和场景有关,基本联想到新增的动态链接库,在两台机器的安装路径不一致。

       第三步:基本确立DLL加载的问题,思考如何避免。查看原有代码逻辑对DLL进一步封装为COM接口,加载COM接口不需要路径,仅一个ID值就能识别,换成COM方式加载后就避免了上述问题。

       足现对已有代码熟悉的重要性。

六、多调试而不是去猜bug原因会事半功倍

        如下调试要常备:GetLastError之ErrorCode、单步Debug调试、asm –int 3调试(内联宏汇编,int表示触发软中断,3是中断号,这个依赖于具体的操作系统。解决常规断点调试解决不了的问题,如对EXE、DLL调试,如1000次循环在999次挂掉的调试)。

        笔者曾遇到Http访问能正确获取页面信息,但是换成Https页面就不可以的bug。访问Https获取页面内容bug的解决就是通过GetLastError的错误码,得知需要绕过SSL认证获取页面信息,并进一步添加Flag标记变量将SSL认证回避掉。

        以VC6.0为例,是可以通过View-->Debug Windows --> Call Stacks 查看调用堆栈的。如下图所示:

        对于复杂的功能实现,有了函数调用堆栈会加快我们的分析。

七、仅在必要的时候和原作者联系

       即便一个项目组中,因为工作了大家都比较忙,各自手里都有任务量,尽量自己去解决。即便非得去向原作者咨询问题,也要事先将待问问题的思路、自己的想法在本上都记录好,确保高效。

       个人体会:工作了,非在学校,大家的时间都特别宝贵,如果你耽误了别人的时间很可能导致别人进度的延误。而在学校,笔者曾经帮别人用6个小时多的时间解决word2010,2007,2003卸载不干净的问题。工作后会发现6个小时,是工作一天的3/4的时间,忒宝贵了

        2014-1-12 pm17:40思于家中床前


推荐阅读:

【1】开源代码分析技巧之一——打印调用逻辑

http://blog.csdn.net/laoyang360/article/details/12676131

【2】开源代码分析技巧之二——gdb单步调试

http://blog.csdn.net/laoyang360/article/details/14102181

【3】开源代码分析技巧之三——老外如是说

http://blog.csdn.net/laoyang360/article/details/16897117

【4】开源代码分析技巧之四——国外技术社区提问

http://blog.csdn.net/laoyang360/article/details/16897827

 

作者:铭毅天下

转载请标明出处,原文地址:http://blog.csdn.net/laoyang360/article/details/18186529

如果感觉本文对您有帮助,请点击‘顶’支持一下,您的支持是我坚持写作最大的动力,谢谢!

©️2020 CSDN 皮肤主题: Age of Ai 设计师:meimeiellie 返回首页