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

article/2024/7/17 20:36:33

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

在正式开始之前,简单介绍一下背景。其实这个问题并不复杂,之所以难缠,反倒是环境导致的。博主需要在一个双核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条件不执行,在不动函数拼写错误的情况下,就需要将变量值改为很大的值才行。我们也顺便验证一下:

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

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

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


http://www.ngui.cc/article/show-1200640.html

相关文章

AtCoder Beginner Contest 303——A-E题讲解

蒟蒻来讲题,还望大家喜。若哪有问题,大家尽可提! Hello, 大家好哇!本初中生蒟蒻讲解一下AtCoder Beginner Contest 303这场比赛的A-E题! A - Similar String 原题 Problem Statement Two characters x x x and y…

VUE SAP、 MPA,,组件开发、VDOM、双向数据绑定

单页面应用(spa) 概念:只有一个html页面,所有跳转方式都是通过组件切换完成的。 优点:页面之间跳转流畅、组件化开发、组件可复用、开发便捷、易维护。 缺点:首屏加载较慢,加载整个项目中使用的…

Android Jetpack组件库(第七部分)---UI工具包 Compose

Android Jetpack 是 Google 推出的一整套帮助 Android 应用程序开发的库、工具包和架构指南,旨在为 Android 应用程序提供更快,更轻松,更稳定的开发体验。自推出以来已经发展成了一个庞大的技术生态系统,包括了许多使用方便、功能…

单例模式8种写法

0. 为什么需要单例模式? 节省内存和计算保证结果正确方便管理 使用场景: 1. 饿汉式(静态常量)—推荐指数:★★☆☆☆ 优点:不会有线程安全问题。 缺点:在类加载的时候就创建对象,…

CentOS安装jdk、tomcat、apache

一、安装JDK8 centos 创建/home/software文件夹 安装好xshell与xftp并连接centos jdk官网https://www.oracle.com/java/technologies/downloads/#java8 下载 上传/home/software 解压缩 tar -zxvf jdk-8u371-linux-x64.tar.gz 重命名 mv jdk1.8.0_371 jdk8添加环境变量…

美国金融科技公司SoFi的增长难以持久,股价也将下跌

来源:猛兽财经 作者:猛兽财经 公司介绍 SoFi Technologies(SoFi)是一家来自美国的知名金融科技公司,自2011年成立以来,已成为领先的个人理财在线平台。SoFi为年轻的高收入客户提供多样化的产品和服务,包括学生和汽车贷…

sql server 字符串链接,及表连接多个值显示连接显示为一列 STUFF for xml path

sql server 字符串链接,及表连接多个值显示连接显示为一列 STUFF for xml path STUFF ( character_expression , start , length , replaceWith_expression ) 以下示例从第一个字符串 abcdef 的第 2 个位置 (b) 开始删除三个字符,然后在删除位置插入…

I.MX RT1170加密启动详解(4):OTFAD XIP加密运行代码

本节将介绍基于AES加密的OTFAD引擎,它可以在不影响AES-128-CTR性能的情况下实时解密数据。OTFAD包括对AES密钥展开机制的完整硬件支持,它可以解密最多4个唯一的AES上下文。每个上下文都有一个用户定义的128位的Image Encryption Key(IEK)、一个64位的计数…

快手三面全过了,却因为背调时leader手机号造假,导致offer作废了!

这是一个悲伤的故事: 快手本地三面全过了,但因为背调时leader手机号造假,导致offer作废了。 楼主感叹:大家背调填写信息时,一定要慎重再慎重,不要重复他的悲剧! 网友愤慨,照这么说&a…

【每日一题Day225】L1156单字符重复子串的最大长度 | 贪心+滑动窗口

单字符重复子串的最大长度【L1156】 如果字符串中的所有字符都相同,那么这个字符串是单字符重复的字符串。 给你一个字符串 text,你只能交换其中两个字符一次或者什么都不做,然后得到一些单字符重复的子串。返回其中最长的子串的长度。 思路&…