当前位置:首页 > 探索

程序修复工具

我电脑里躺着个修了三年都没修好的程序bug,每次运行到第47行就崩。修复崩溃日志写得倒是工具很勤快,一晚上能攒出几百兆,程序全是修复同一个错误码。我试过自己改,工具改完第47行,程序第48行又炸了。修复那感觉就像在拆一个俄罗斯套娃,工具每一层拆开都有更小的程序一个等着你。

后来我用了程序修复工具。修复不是工具那种网上吹得天花乱坠的AI自动补丁神器,就是程序最普通的静态分析器加内存检测器。工具跑起来,修复屏幕上滚过几千条警告,工具大部分是废话——什么“未使用的变量”“建议使用const修饰符”之类的。但我还是耐着性子翻,翻到第两千多条的时候,看见一条:“在函数foo()中,指针可能在释放后被引用。”

就这一条。我盯着看了半分钟,突然明白了。问题根本不在第47行,在我三个月前写的一个清理函数里。那个函数把一块内存释放了,但有个全局指针还指着那块已经还给系统的地儿。程序跑得快的时候没事,跑得慢的时候那块内存被别的数据覆盖了,第47行再去读,读出来一堆垃圾,直接崩溃。

工具不会替你改代码,它只会告诉你哪儿疼。但很多程序员连哪儿疼都不知道,就知道对着崩溃日志干瞪眼。日志告诉你“第47行出错”,你就去改第47行,改完还是错。工具的作用是把“第47行出错”翻译成人话:“你三个月前在另一个文件里干了一件蠢事,现在报应来了。”

这让我想起一个同事。他写了个服务,内存占用一天涨一个G,重启就好,不重启就卡死。他怀疑是内存泄漏,但查了三天没查出来。后来用了个heap profiler,跑了一晚上,生成一张内存分配图。图里能看到一块内存被分配了十万次,每次只释放九万九千九百九十九次。就少一次。那个漏网的地方藏在一个异常处理的catch块里——正常流程走不到,只有网络超时才会触发。他平时测试都用本地环境,网络从来不超时,所以这bug活了大半年没人发现。

程序修复工具最让人上瘾的地方是它的反馈速度。你改一行代码,跑一遍测试,工具告诉你“这次少了一百个警告”。那种数字往下掉的感觉,比打游戏刷经验值还爽。但也有副作用——你会开始依赖它,就像依赖GPS开车一样。开久了,自己认路的能力就退化了。我见过一个刚入行的,写代码全靠工具纠错,工具不报错他就不知道代码写得对不对。有次工具因为许可证过期没法用了,他对着屏幕发呆了二十分钟,连一个排序函数都不敢写。

工具是拐杖,不是腿。但话说回来,人长了腿也得偶尔用用拐杖,尤其是你腿瘸的时候。我现在那个修了三年的bug,其实两年前就用工具定位到了,但一直没彻底修干净——因为每次修完一个漏洞,工具又能查出下一个。到后来我分不清是在修bug,还是在跟工具玩捉迷藏。最后我干脆把那个模块整个重写了,删了一千多行旧代码。工具跑完,警告数从两千多降到十几个。

那十几个警告我到现在也没管。我知道它们是什么——无非是些风格建议,加不加const的事儿。程序能跑,用户不骂,就够了。工具教会我的最重要一件事是:不是所有警告都值得修,但所有崩溃都有原因。原因找到了,修不修,看你心情。

分享到: