当你怀疑电脑的时候,就是该换个方法的时候了

做软件开发的朋友们,干的时间长了,相信都会有过类似的体验:一个问题查了很久很久,代码检查了很多遍很多遍,到最后都要怀疑电脑了,突然发现是一个特别隐蔽的错误导致的,而这种错误通常不涉及逻辑流程,却特别容易瞒天过海。比如可能是掺杂了一个中文字符,可能是少写了一个分号,可能是变量重名了,可能是类型强转了,可能是变量未初始化,可能是指针指错了等等等等。反正都是一些不引人注意的细节导致了问题的难缠。今天,博主就遇到了一个类似的问题。

在正式开始之前,简单介绍一下背景。其实这个问题并不复杂,之所以难缠,反倒是环境导致的。博主需要在一个双核CPU上分别实现不同的功能。因为各种原因,导致只能通过CPU0来访问调试。如果要调试CPU1上的程序,那么将相关量写入共享内存,然后通过CPU0读出,以此间接调测。

因为这种方式比较麻烦,所以要调试CPU1的时候,内心总是抗拒的。尤其是当在CPU1中已经增加不少的调试变量后,更加的抗拒新增调测变量。但是,上天总是公平的,一份付出一分收获,自认为没有问题而不愿意调测的代码,执行时往往隐含着神秘的错误。所以,让代码可测,确实是有道理的。

关于这方面,其实已经有很多好的经验了。比如,典型的测试驱动开发,就让代码的可测性可控性大大增强了。但是偷懒是人的本性。虽然说懒是促进人类进步的动力,但那是另一种“懒”,而非这里所说的真的懒。很多时候,我们都是懒得写测试代码,而是直达目的,而且是边想边写,边写边测,缺少设计、规划。为此,很多资深开发者,实力前辈通过各种渠道倡议了许多好用的软件工程方法,包括前面的测试驱动开发,包括敏捷开发,包括重构等等。但是(我们已经讲了很多但是了),具体到开发实践中,正真能够落实的又有多少呢?往往都是入坑了,才慨叹悔不当初啊。所以,经过此次入坑的经验教训,博主也是更加坚定了坚持写测试用例来验证代码逻辑的做法。俗话说磨刀不误砍柴工,这才是比解决问题本身更大的收获。

好了,现在我们具体看看是个什么问题。

我们先看看代码。将关键部分提取出来,整理如下:

#include "stdio.h"

static int state = 0;

int get_state() {

   state = 2;

   return state;

}

int main(int argc, char **argv)

{

   int cur_state = 1;

   if (get_state > cur_state) {

      printf("state changed \n");

   }

   return 0;

}

不知大家看出啥了没有。我们编译看看。

编译提示如下:

可以看到,编译有一个警告。当然,这里可以清晰的看到该警告,但是在工程中,一旦有很多警告被忽略的话,那这种警告也就当做不存在了。

我们执行代码,看看效果:

If条件被执行了。在工程中,这种情况可能还不会触发问题。我们修改一些代码,再看看。

这次,我们把状态改成3,如果是函数的话,2大于3就不成立了,但是可以看到,if条件仍然被执行了。

其实这个问题的原因很简单,我们在编写代码过程中,出现了拼写错误,丢失了函数的括弧,编译器将函数名当做函数指针,用一个指针值参与运算了。自然,条件会始终执行。要想让if条件不执行,在不动函数拼写错误的情况下,就需要将变量值改为很大的值才行。我们也顺便验证一下:

可以看到,符合我们的预期。

这种错误,一般是代码编辑工具自动联想时导致的。如果在大工程中出现,还是很隐蔽的,如果存在于一个犄角旮旯的地方,那测出的概率就小,隐患就大。

好了,总结一下,有两点:一,俗话说的不听老人言,吃亏在眼前还是很有道理的。二,由怀疑程序到怀疑电脑推而广之,当你怀疑人生的时候,就该考虑换个活法了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龙赤子

你的小小鼓励助我翻山越岭

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值