使用未初始化的局部变量是引起程序崩溃的一个比较普遍的原因,
许多Windows API都接受或则返回一些结构体参数,结构体如果没有正确的初始化,也很有可能引起程序崩溃。大部分Windows API结构体都必须有一个cbSIze参数,这个参数必须设置为这个结构体的大小。
注意:千万不要用ZeroMemory和memset去初始化那些包括结构体对象的结构体,这样很容易破坏其内部结构体,从而导致程序崩溃。
在函数设计的时候,对传入的参数进行检测是一直都推荐的。例如,如果你设计的函数是公共API的一部分,它可能被外部客户端调用,这样很难保证客户端传进入的参数就是正确的。
在指针使用之前,不检测是非常普遍的,这个可以说是我们引起软件崩溃最有可能的原因。如果你用一个指针,这个指针刚好是NULL,那么你的程序在运行时,将报出异常。
如果你的函数创建了一个对象,并要将它作为函数的返回参数。那么记得在使用之前把他复制为NULL。如不然,这个函数的调用者将使用这个无效的指针,进而一起程序错误。
在内存释放之后,务必将指针复制为NULL。这样可以确保程序的没有那个地方会再使用无效指针。其实就是,访问一个已经被删除的对象地址,将引起程序异常。
在释放一个句柄之前,务必将这个句柄复制伪NULL(0或则其他默认值)。这样能够保证程序其他地方不会重复使用无效句柄。
如果你分配一个单独的对象,可以直接使用new ,同样你释放单个对象的时候,可以直接使用delete。然而,申请一个对象数组对象的时候可以使用new,但是释放的时候就不能使用delete ,而必须使用delete[]:
有时候,程序需要动态分配一段缓冲区,这个缓冲区是在程序运行的时候决定的。例如,你需要读取一个文件的内容,那么你就需要申请该文件大小的缓冲区来保存该文件的内容。在申请这段内存之前,请注意,malloc() or new是不能申请0字节的内存,如不然,将导致malloc() ornew函数调用失败。传递错误的参数给malloc() 函数将导致C运行时错误。
Asserts用语调试模式检测先决条件和后置条件。但当我们编译器处于release模式的时候,Asserts在预编阶段被移除。因此,用Asserts是不能够检测我们的程序状态。
断定一个函数执行一定成功是一种常见的错误。当你调用一个函数的时候,建议检查下返回代码和返回参数的值。如下代码持续调用Windows API ,程序是否继续执行下去依赖于该函数的返回结果和返回参数值。
如果你经常使用用享对象指针,如COM 接口等,那么建议使用智能指针来处理。智能指针会自动帮助你维护对象引用记数,并且保证你不会访问到被删除的对象。这样,不需要关心和控制接口的生命周期。
尽可能的使用静态缓存,因为编译器会自动释放这样的空间。
当你后面不再使用的时候,应该手动释放之前分配的内存.不要笑,遇到过很多从java转C++的程序员都会这样想。
C++中尽量使用new和delete ,而不是用calloc/malloc(建议仅限C语言使用)。
要记住new和delete成对使用,千万不要new出来的内存,用free释放。
在函数传递指针的所指向的缓存大小的时候,记得一定告诉被调用函数你的缓存区大小,同时返回被调用函数操作后的实际大小。
当发布你的代码库sdk时候,提供封装的new和delete函数,这样可以在单线程或者多线程运行的时候避免很多问题。
当进行动态内存分配的时候,使用无符号数去统计分配内存的空间大小。这样可以剔除负数,同时你也得记得检查分配的内存空间最大值。
不要循环分配和释放内存,这样会降低程序效率,也可能会引起一些安全事故
释放指针之后给其赋值为NULL 这样可以避免后面内存使用时的突发事件。
ZeryMerory和memset
函数
在当缓冲区的字符串超出生命周期的时候,会被编译器优化,从而缓冲区的内容会被恶意软件捕捉到。引起软件安全问题,特别是对于密码这 些比较敏感的信息而说。而SecureZeroMemory则不会引发此问题,保证缓冲区的内容会被正确的清零。如果涉及到比较敏感的内容,尽量使用 SecureZeroMemory函数
当要在内存中存储像密码这样敏感的信息数据,释放删除之后,使用随机数进行覆盖。要明白free或者delete只是使得先前分配的内存当前不可用,但是并没有在删除它在内存中的数据。
检查你的程序是否有内存泄露的一个简单方法就是在windows或者linux系统下利用任务管理器,查看内存使用量。
千万不要分配大小为0的字节空间,该行为属于未定义,不可预知。
记得在使用之前,经常检查内存分配的指针,千万不要使用无效的指针,是程序产生异常和崩溃。
当分配集合的时候,使用向量std::vector
当在使用new关键字的时候,记得使用try-catch 语句块,当不需要使用语句块的时候,使用std::nothrow进行声明,如thing * pt= new (std::nothrow)thing[100];
在使用const和inline的时候尽量不要单独定义,尽量封装统一文件或者类里面。
对于非基本数据类型的变量,在函数参数传递时,尽量使用指针或者引用。
个人整理和总结,欢迎大家继续补充