越维护代码越感觉心惊肉跳的

       很奇怪,今天一大早来到公司我就有这种感觉。大概我感觉昨天我改正的那个bug其中可能还隐含了“杀气”!然后我仔细的再次阅读了一遍,  果然,里面隐藏了一个不定时“炸弹”——有一个读文件操作,我没有添加条件判断语句。虽然说要读取的这个文件,使用该产品的用户是几乎没可能会去手动查看的(里面就一串随机的序列号,做标记值使用),但是,不排除出现意外,导致程序读取不成功。然后我打开后,直接使用文件 句柄写,就可能由于打开不成功导致写的时候程序崩溃!!!看来维护了这么久的代码,察觉意外的感觉还是多少有点的。然后我“心惊肉跳”的感觉确实是今天才有的,借此机会,总结一下个中原因,跟大家说说,希望大家的代码中不会出现再让自己活着别人产生这种不愉快的感觉。
        目前程序中的bug,基本可基于这些原因产生一个大致的分类:线程、进程用完后对资源没有快速的释放;产品升级导致前一个版本的部分文件在新的版本中不兼容;内存溢出;产品运行时内存不足,导致用户卡。
        一、线程、进程用完后对资源没有快速的释放
        这个问题不太好总结,先说说出现问题的场景和现象吧。有个产品,能够以列表的形式列出一个相关主题的所有文件,这些文件都是网络上抓取的,以“文件名.pdf”形式排列在列表中,用户点击某个文件名后,程序会启动下载线程,下载完毕会调用系统的读取pdf格式的软件打开该文件,同时下载后会放置到一个指定目录:假如用户没有指定目录,放到一个默认目录中,假如用户指定了目录,则将这部分文件下载完后移动到指定目录,然后打开。实际情况是这样的,文件被放置在一个反url形式的目录下:如url为:
https://www.baidu.com/s?ie=%B2%E5%98%9B7,那么可能会被放置在这个目录:“……/B7/89/E5/B2/iE/utf-8格式文件名.pdf”。然后你去代码中查找原因,逻辑都没错,但是在log中发现了这样一条记录:文件XXXX 移动到XXXX 失败,MoveFileEx返回值[32],然后百度了一下这个返回值发现:“〖32〗-进程无法访问文件,因为另一个程序正在使用此文件。”问题已经找到了,那么是谁还在抓着这个资源不放呢?原来,此处有两个线程一起工作,  线程A下载和打开,线程B移动文件。显然,在移动文件的时候线程A还试图打开这个文件,B线程失败了,但是程序必须要放在一个位置啊,系统就在当前程序 家目录上以url派生了一个目录默认放置。如何解决:将打开文件的操作移动到线程B中,A下载完后就不再负责其他事情。总结一下这个问题:资源释放,线程同步等基本功,之前写代码的都没有意识到;测试的时候也不彻底,导致后期徒增工作量。
        二、产品升级导致前一个版本的部分文件在新的版本中不兼容
        也还是先来描述一下这个的场景和现象。产品X,目前升级到了2.0,但是用户有一些配置文件是1.0时候配置好,并保存在本地的。升级完发现,这些配置不起作用了!现象就是:程序加载完配置文件后,一直在loading配置项。详细查看了一下代码,发现:1.0版本的配置文件不需要增加配置项的后缀,而2.0版本必须有后缀才可以读取。怎么办?为了不让用户流失,添加一个模块,让程序启动过程中依次去读取用户的配置文件,并将文件内容上传服务器,在服务器那边给配置项匹配上合适的后缀,写回到配置文件。总结一下,该问题出现了,我觉得多少算是合理的。只是在打算升级2.0前大家都没有全面的检查程序的功能模块,导致了用户使用上的不便。
        三、内存溢出
        这个分类产生的问题,可多了去了。比如说,你以为你定义好的线程池是可以从服务器上接受那些数据的,但是,你没想到,客户一次运行了10天半个月,结果某一天就“爆”了!然后看dump文件:不对啊,不应该啊!后来找用户一问:原来如此。改呗!或者说,有一个字符串,我定义死了就应该是17个字符在里面,用来保存从文件中读取的内容(文件里面只有一行且是16个字符)。读出来后,for循环按下标依次赋值个另一个字符串,但是中途程序break了!debug的时候发现,为什么读出来的是5个字符,这样我for16次不break才怪!然后查看这一串逆天字符明明看到16个却只能读取出5个的原因:这一串字符是utf-8格式的,里面有一个中间有一个编码是换行,结果你按行读取的时候只读取到了前半部分……夭寿啊!诸如此类。总结一下原因:这类问题我觉得不要过于苛责。首先要能将显然的内存越界问题改正,在读取内存块 的时候要将读取的内存做一次检测,看和想象中的是否相符,使用了这些手段,做一个基本的保证。将来要是还出现了这个问题,就真的不是人在一开始可以解决掉,只能在发现问题的时候改正问题。
        四、产品运行时内存定死,导致用户卡
        场景:产品XXX,该产品会抓取一些地区符合某类特征的信息。但是不同地区这些信息所需要的消耗的内存是不一样的,版本1中将这个内存消耗定死了,
    比如我就给1个8M的buffer去接受,导致用户卡着。
        解决方案:根据不同地区的不同情况,动态调整改内存大小。
        总结:这个没有总结,毕竟这种情况是不多见的。只能说我们遇到一些很奇葩的客户,他们的电脑很老,操作系统版本很低。不舍得加内存。我当初是想
    直接将这个buffer扩大几倍就行了,但是有了这个实际情况,还真是必须通过动态调整才能让用户用的舒服一点。

        最后是一些其他问题总结了,比如说,你代码中有主动去请求某项资源的操作,那一定要判断一下请求是否成功,比如我早上发现的“杀气”。还有,不要随便使用return,
特别是一个void函数,我就看过一个void函数,里面不止一个return啊,我连哪里返回了都不知道!!!最后,程序中尽量多一些log,多一些捕捉异常的语句,if——else一定要配对使用(哪怕你的else里面是空,也要有一个),诸如此类。
        就写到这里吧,希望对你有帮助。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值