首页 > 代码库 > 强壮你的C和C++代码30个小细节

强壮你的C和C++代码30个小细节

1 初始化局部变量

使用未初始化的局部变量是引起程序崩溃的一个比较普遍的原因,

2 初始化WINAPI 结构体

  许多Windows API都接受或则返回一些结构体参数,结构体如果没有正确的初始化,也很有可能引起程序崩溃。大部分Windows API结构体都必须有一个cbSIze参数,这个参数必须设置为这个结构体的大小。

  注意:千万不要用ZeroMemory和memset去初始化那些包括结构体对象的结构体,这样很容易破坏其内部结构体,从而导致程序崩溃。

3 检测函数输入参数有效性

  在函数设计的时候,对传入的参数进行检测是一直都推荐的。例如,如果你设计的函数是公共API的一部分,它可能被外部客户端调用,这样很难保证客户端传进入的参数就是正确的。

4 检测指针变量有效性


  在指针使用之前,不检测是非常普遍的,这个可以说是我们引起软件崩溃最有可能的原因。如果你用一个指针,这个指针刚好是NULL,那么你的程序在运行时,将报出异常。

5 初始化函数输出参数

  如果你的函数创建了一个对象,并要将它作为函数的返回参数。那么记得在使用之前把他复制为NULL。如不然,这个函数的调用者将使用这个无效的指针,进而一起程序错误。

6 释放指针和对象

  在内存释放之后,务必将指针复制为NULL。这样可以确保程序的没有那个地方会再使用无效指针。其实就是,访问一个已经被删除的对象地址,将引起程序异常。

7 清除释放的句柄

  在释放一个句柄之前,务必将这个句柄复制伪NULL(0或则其他默认值)。这样能够保证程序其他地方不会重复使用无效句柄。

8 使用delete[] 操作数组

  如果你分配一个单独的对象,可以直接使用new ,同样你释放单个对象的时候,可以直接使用delete。然而,申请一个对象数组对象的时候可以使用new,但是释放的时候就不能使用delete ,而必须使用delete[]:

9 小心分配内存

  有时候,程序需要动态分配一段缓冲区,这个缓冲区是在程序运行的时候决定的。例如,你需要读取一个文件的内容,那么你就需要申请该文件大小的缓冲区来保存该文件的内容。在申请这段内存之前,请注意,malloc() or new是不能申请0字节的内存,如不然,将导致malloc() ornew函数调用失败。传递错误的参数给malloc() 函数将导致C运行时错误。

10 小心使用assert

  Asserts用语调试模式检测先决条件和后置条件。但当我们编译器处于release模式的时候,Asserts在预编阶段被移除。因此,用Asserts是不能够检测我们的程序状态。

11 检查函数返回值

  断定一个函数执行一定成功是一种常见的错误。当你调用一个函数的时候,建议检查下返回代码和返回参数的值。如下代码持续调用Windows API ,程序是否继续执行下去依赖于该函数的返回结果和返回参数值。

12 使用智能指针

  如果你经常使用用享对象指针,如COM 接口等,那么建议使用智能指针来处理。智能指针会自动帮助你维护对象引用记数,并且保证你不会访问到被删除的对象。这样,不需要关心和控制接口的生命周期。

内存使用方面的一些建议
13

尽可能的使用静态缓存,因为编译器会自动释放这样的空间。

14

当你后面不再使用的时候,应该手动释放之前分配的内存.不要笑,遇到过很多从java转C++的程序员都会这样想。

15

C++中尽量使用new和delete ,而不是用calloc/malloc(建议仅限C语言使用)。

16

要记住new和delete成对使用,千万不要new出来的内存,用free释放。

17

在函数传递指针的所指向的缓存大小的时候,记得一定告诉被调用函数你的缓存区大小,同时返回被调用函数操作后的实际大小。

18

当发布你的代码库sdk时候,提供封装的new和delete函数,这样可以在单线程或者多线程运行的时候避免很多问题。

19

当进行动态内存分配的时候,使用无符号数去统计分配内存的空间大小。这样可以剔除负数,同时你也得记得检查分配的内存空间最大值。

20

不要循环分配和释放内存,这样会降低程序效率,也可能会引起一些安全事故

21

释放指针之后给其赋值为NULL 这样可以避免后面内存使用时的突发事件。

22

ZeryMerory和memset函数在当缓冲区的字符串超出生命周期的时候,会被编译器优化,从而缓冲区的内容会被恶意软件捕捉到。引起软件安全问题,特别是对于密码这 些比较敏感的信息而说。而SecureZeroMemory则不会引发此问题,保证缓冲区的内容会被正确的清零。如果涉及到比较敏感的内容,尽量使用 SecureZeroMemory函数

23

当要在内存中存储像密码这样敏感的信息数据,释放删除之后,使用随机数进行覆盖。要明白free或者delete只是使得先前分配的内存当前不可用,但是并没有在删除它在内存中的数据。

24

检查你的程序是否有内存泄露的一个简单方法就是在windows或者linux系统下利用任务管理器,查看内存使用量。

25

千万不要分配大小为0的字节空间,该行为属于未定义,不可预知。

26

记得在使用之前,经常检查内存分配的指针,千万不要使用无效的指针,是程序产生异常和崩溃。

27

当分配集合的时候,使用向量std::vector<thing>vt(100,thing()),而不是使用thing* pt = new thing[100];

28

当在使用new关键字的时候,记得使用try-catch 语句块,当不需要使用语句块的时候,使用std::nothrow进行声明,如thing * pt= new (std::nothrow)thing[100];

29

在使用const和inline的时候尽量不要单独定义,尽量封装统一文件或者类里面。

30

对于非基本数据类型的变量,在函数参数传递时,尽量使用指针或者引用。


个人整理和总结,欢迎大家继续补充