项目最的出了几次运营事故,都是因为使用自乘、自加、自減运算,错改了非局部变量,导致将用户数据写溢出,最终只能进行回档处理。先给大家展示一下,漏出bug的代码吧。
代码展示
代码1
作者本意是给每个用户补偿固定值的金币数,即如果addmoney为500,那每个用户都加500,但这里因为把addmoney作了自加操作,结果后面的使用成了累加,如果这里合理的使用const并考虑到变量的作用域,就不会出错。修改后代码如下:
这里,对addmoney加上const,同时变量名全部大写表示为常量,同时,修改了id和currentmoney的作用域。
代码2
作者的本意是想从配置中得到用户应加上的金币数,并给用户加上,代码中使用了自乘操作,但问题就出在引用上,结果是配置中的静态成员变量被修改,下一次调用将会是上次调用的结果再乘上multi,最终将溢出。这段代码的问题比较多,一是直接使用类的静态成员变量,这种变量应声明为private或protected,而通过接口返回,如果返回引用或指针的话,要加上const。另外,如果类的作者一定要让调用者直接使用拒绝提供接口的话,一定要对引用加上const,防止被误改。修改如上:
当然,最佳的修改方式应该是这样的:
问题总结
其实这里的问题,通过良好的编程习惯是可以得到规避的,我总结了几点:
1. 使用局部变量,保证变量的最小作用域。
2. 对于明确不需要修改的变量,无论是传入参数、局部变量或返回值,加上const。
3. 慎用指针和引用,接口返回指针和引用时,加上const,防止调用者误操作。
4. 避免直接使用全局变量和类静态变量,类静态变量一定要通用带有const的接口返回,全局变量一样。
5. 对接口进行白盒测试,跑N轮,保证输出合法性。
良好的编程习惯和编程风格是项目成功的关键,不要为了高效而写晦涩的代码, 因为对项目而言,可读性和可维护性远比性能重要。最后重申一下本文的主旨“多使用const, 慎用自运算”!