您当前的位置:首页 > 电脑百科 > 程序开发 > 编程百科

代码防御性编程的十条技巧

时间:2020-08-24 16:40:02  来源:  作者:
代码防御性编程的十条技巧

 

1 什么是防御性编程

顾名思义,防御性编程是一种细致、谨慎的编程方法。为了开发可靠的软件,我们要设计系统中的每个组件,以使其尽可能的”保护”自己。我们通过明确地在代码中对设想进行检查,这是一种努力,防止我们的代码以将会展现错误行为的方式被调用。

防御性编程使我们可以尽早的发现较小的问题,而不是等到它们发展成大的灾难的时候才发现。其开发软件的过程是:

代码防御性编程的十条技巧

 

下面总结了一些防御性编程的反对和支持者的意见:

反对者:

  1. 它降低了代码的效;即使是一个很小的额外代码也需要一些额外的执行时间。它对于一个函数来说也许不要紧,但是对于一个由10万个函数组成的系统,问题就变得严重了。
  2. 每种防御性的做法都需要一些额外的工作;

支持者:

  1. 防御性编程可以节省大量的调试时间,使你可以去做更有意义的事情。
  2. 编写可以正常运行、只是速度有些慢的代码,要远远好过大多数时间都正常运行、但是有时候会崩溃的代码。
  3. 防御性编程避免了大量的安全性问题。

防御性编程技巧

  1. 使用好的编码风格和合理的设计

采用良好的编码风格,来防范大多数编码错误。如:

  • const关键字:

关键字const可以给读你代码的人传达非常有用的信息。例如,在函数的形参前添加const关键字意味着这个参数在函数体内不会被修改,属于输入参数。

同时,合理地使用关键字const可以使编译器很自然的保护那些不希望被修改的参数,防止其被无意的代码修改,减少bug的出现。

  • volatile关键字:

在一些并行设备的硬件寄存器(如状态寄存器),中断服务子程序中会访问到的全局变量以及多线程应用中被几个任务共享的变量前使用volatile关键字来防止编译优化。

  • static关键字:
  1. 函数体内static变量的作用范围为该函数体,不同于auto变量,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值。
  2. 在模块内的static全局变量可以被模块内的所有函数访问,但不能被模块外其它函数访问。
  3. 在模块内的static函数只可能被这一模块内的其它函数调用,这个函数的使用范围被限制在声明它的模块内。
  • 位操作运算中,尽可能使用<<、 >>、 &、|等运算符,尽可能少使用/、%、*运算符。
  • 变量和函数的命名要有意义,并且尽可能做到一个函数只做一件事情。
  • 多采用面向对象的思想来编写代码。
  • 在投入到编码工作之前,先考虑大体的设计方案,这也非常关键。
  1. 不要仓促的编写代码

欲速则不达,每敲一个字,都要想清楚你要输入的是什么。在写每一行时都三思而后行。可能会出现什么样的错误?你是否已经考虑了所有可能出现的逻辑分支?放慢速度,有条不紊的编程虽然看上去很平凡,但这的确是减少缺陷的好办法。

C语言编程中,追求速度的程序员经常会出现的一个问题就是将”==”错误的输入为”=”,而有些编译器并不会警告,这就会造成问题。

  1. 不要相信任何人

这里是指用怀疑的眼光来审视所有的输入和所有的结果,直到你能证明这段代码是正确的时候为止。

  1. 编码的目标要清晰,而不是简洁

简单是一种美,不要让你的代码过于复杂。即编写的代码一定要逻辑清晰,可读性强。

  1. 编译时打开所有警告开关

在你的代码中产生任何警告信息,都应立即修正代码。要知道警告的出现总是有原因的。即使你认为某个警告无关紧要,也不要置之不理。

  1. 使用安全的数据结构

我们最常见的一些安全隐患大概是由缓冲溢出引起的。缓冲溢出是由于不正确的使用固定大小的数据结构而造成的。例如,如下这个代码:

char * unsafe_copy(const char * source)
{
   char *buffer = new char[10];
   strcpy(buffer,source);
   return buffer;
}

如果source中的数据长度超过10个字符,它就会造成其它问题。我们可以改成如下形式:

char * safe_copy(const char * source)
{
   char *buffer = new char[10];
   strncpy(buffer,source,10);  //用strncpy代替strcpy可以保护这个代码段
   return buffer;
}
  1. 检查所有的返回值

如果一个函数返回一个值,他这样做肯定是有理由的。检查这个返回值,如果返回值是一个错误代码,你就必须辨别这个代码并处理所有的错误。不要让错误悄无声息的侵入你的程序;大多数难以察觉的错误都是因为程序员没有检查返回值而出现的。

  1. 审慎的处理内存

对于在执行期间所获取的任何资源,必须彻底释放。

  1. 在声明位置初始化所有变量

如果你意外的使用了一个没有初始化的变量,那么你的程序在每次运行的时候都将得到不同的结果,这取决于当时内存中的垃圾信息是什么。这样会造成很多随机的行为,给查找带来很多的麻烦。因此,需要在声明每个变量的时候就对它进行初始化。

  1. 同时,平时编码时还要注意一些细则
  • 提供默认的行为:Switch语句中将default case的执行明示出来。同样地,如果你要编写一些不带else子句的if语句,停下来想一想,你是否该处理这个逻辑上的默认情况
  • 检查数值的上下限:确保每次运算数值变量都不会溢出,即数据类型的使用要谨慎
  • 注意强制转换是否合理
  • 声明变量,可以使变量的声明位置与使用它的位置尽量接近,从而防止它干扰代码的其他部分
  • 加合理的异常处理、日志文件
  • 正确设置常量

优秀的程序应该做到:

  • 关心代码是否健壮
  • 确保每个设想都显示地体现在防御性代码中
  • 希望代码对无用信息的输入有正确的行为
  • 在编程的时候认真思考自己所编写的代码
  • 编写可以保护自己不受其他人的愚蠢伤害的代码。


Tags:防御性编程   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
1 什么是防御性编程?顾名思义,防御性编程是一种细致、谨慎的编程方法。为了开发可靠的软件,我们要设计系统中的每个组件,以使其尽可能的”保护”自己。我们通过明确地在代码中...【详细内容】
2020-08-24  Tags: 防御性编程  点击:(93)  评论:(0)  加入收藏
▌简易百科推荐
1. 前言了解响应式编程,首先我们需要了解函数式操作和Stream的操作,下面我们简单的复习一下喽。1.1 常用函数式编程函数式接口中我们先来回顾一下Java中的函数式接口。常见的...【详细内容】
2022-07-15  二哥学Java    Tags:编程   点击:(1)  评论:(0)  加入收藏
在本文中,我们将学习如何使用 Next.js、 Prisma、 Postgres 和 Fastify 构建一个 Full-stack 应用程序。在本文中,我们将学习如何使用 Next.js、 Prisma、 Postgres 和 Fastif...【详细内容】
2022-07-12  qaseven    Tags:全栈   点击:(9)  评论:(0)  加入收藏
好的软件开发网站有哪些?做软件开发哪些网站能提供帮助呢?这些很多做软件开发的小伙伴都会问到的问题。007出海全球社交流量导航网站,整合了多方出海跨境网站资源,为你介绍出海...【详细内容】
2022-07-08  Chuhai007    Tags:软件开发   点击:(10)  评论:(0)  加入收藏
我们用monkey做压力测试后,会保存一个monkey日志,那如果想快速的分析日志中有哪些异常,我们可以用批处理工具进行快速的筛查,我们一起来看看吧。先编写个小脚本,然后修改为bat后...【详细内容】
2022-07-08  溪流涌动    Tags:monkey   点击:(13)  评论:(0)  加入收藏
白盒测试落地实践分为两个大方向,一个是静态分析,一个是动态分析,当然啦,也可以叫做静态测试和动态测试。那我们如何高质量保效率的做好白盒测试呢?Parasoft已经为您准备好了成熟...【详细内容】
2022-07-08  Parasoft中国    Tags:白盒测试   点击:(11)  评论:(0)  加入收藏
Altium Designer 自带脚本功能的开发项目,可以调用官方AD API接口对原理图或者PCB进行自动操作,本文主要分享开发的流程,和一些基本的概念信息,本文介绍的脚本工具例子可以用在P...【详细内容】
2022-07-07  电子工程师伟哥    Tags:Altium Designer   点击:(21)  评论:(0)  加入收藏
一、目录介绍 前置知识点 NIO Netty 的核心组件 Channel Callback Future 和 Promise 事件和 ChannelHandler Hello World二、前置知识点1、NIO首先我们需要回顾一...【详细内容】
2022-07-06  架构师jickly    Tags:聊天系统   点击:(16)  评论:(0)  加入收藏
1.事件流事件流是对事件执行过程的描述,了解事件的执行过程有助于加深对事件的理解,提升开发实践中对事件运用的灵活度。2.捕获和冒泡捕获阶段是【从父到子】的传导过程,冒泡阶...【详细内容】
2022-07-06  金乾坤    Tags:API   点击:(13)  评论:(0)  加入收藏
刷盘策略CommitLog的asyncPutMessage方法中可以看到在写入消息之后,调用了submitFlushRequest方法执行刷盘策略:public class CommitLog { public CompletableFuture<PutMe...【详细内容】
2022-07-06  Java码农之路    Tags:RocketMQ   点击:(16)  评论:(0)  加入收藏
最近读了本好书-《深度学习推荐系统》,读完不觉全身通畅,于是就有了写这篇文章的想法,把自己的理解和总结分享给大家。 本文将按照从算法到工程的顺序,先介绍一下推荐系统整体...【详细内容】
2022-07-05  InfoQ    Tags:推荐系统   点击:(22)  评论:(0)  加入收藏
相关文章
    无相关信息
站内最新
站内热门
站内头条