内存泄漏及管理--程序开发注意的问题

一。何为内存泄漏

     我们常说的内存泄漏通常指堆内存的泄漏,指我们的程序从堆中分配,使用完必须由程序显示地释放的内存。通常由程序中的malloc、realloc、new等函数分配的内存。在使用完后必须通过free/delete释放该内存块。如果该内存块不再访问却未被释放这就是我们通常所说的内存泄漏,而广义的内存泄漏不仅仅指堆内存的泄漏,还包括系统资源的申请释放,如socket及文件描述符、以及系统分配的对象。这种系统资源的泄漏可能比堆内存泄漏更严重。

二。内存分配

     内存分配有以下几种方式

    a.从静态存储区分配,内存在程序编译的时候就分配好,在程序的整个运行过程都存在。最常见的比如全局变量及静态变量。

    b.栈上分配的内存,在函数执行过程中,函数内部变量在栈上创建,函数执行结束后这些存储单元会自动释放,栈内存分配内置在运算器的指令集中,运算效率高,但分配容量有限。

    c.堆上分配的内存,即动态分配的内存。使用malloc/realloc/new申请的内存,由应用程序在使用完后,通过free/delete释放内存。此内存的生存期由应用程序指定。使用非常灵活(申请/释放由程序决定,申请内存的大小由程序指定),但也是最需要注意的地方,使用不当就会带来许多问题。

三。常见的内存泄漏

    应用程序常见的内存泄漏会有下面几种:

    经常发生。问题代码经常被执行到。每执行一次就会导致一块内存泄漏。带来后果就是程序占用存在不断持续增长。可能的情况不断分配内存,而未被释放,或者在程序退出时一次性释放,但程序是连续运行的,不及时释放内存会导致最终系统资源被耗尽。

    偶然发生。只有在特定情况下才会发生。只有特定条件满足时问题代码才会被执行,导致一块内存泄漏。

    一次性泄漏。问题代码只会被执行一次。

四。程序常见内存问题

    内存错误不仅指内存泄漏。   解决内存错误比较麻烦,首先编译器不会自动发现内在问题。通常在程序运行期间才会出现。而且错误时隐时现,有些错误还很难再现,这都增加了问题改正的难度。

    常见的内存问题有:

    a.使用了未分配或分配未成功的内存。解决方法,在使用前检查指针是否为空,特别是在分配后。 

    b.使用了未初始化的内存。虽然分配成功,但未初始化

  c.内存分配成功并且已经初始化,但操作越过了内存的边界。也就是通常所说的数组越界。

  d.内存泄漏。就是上面所说的问题。

  e.使用了已释放的内存。

  避免内存问题的策略:

  1。程序中的对象调用关系过于复杂,实在难以搞清楚某个对象究竟是否已经释放了内存,此时应该重新设计数据结构,从根本上解决对象管理的混乱局面;

  2。函数的return注意不要返回指向栈内存指针或者引用,因为该内存在函数体结束时会被自动销毁。

  3。使用freedelete释放了内存后,最好将指针设置为NULL。否则会导致产生野指针

  野指针”也就是非法指针,指向垃圾的指针,一般由b,e情况引起的。

五。好的编程习惯

  a.mallocnew申请内存之后,应该立即检查指针值是否为NULL。防止使用指针值为NULL的内存。

  b.不要忘记为数组和动态内存赋初值。防止使用未初始化的内存。

  c.避免数组越界,特别要注意发生1”或者1”操作。

  d.动态内存的申请与释放必须配对,防止内存泄漏。

  e.free/delete释放了内存后,应将指针设置为NULL,防止产生野指针

  f.在未释放指向的内存前不要改变指针的指向,否则会带来内存泄漏。

  另外可以使用内在检查工具对编译好的程序进行分析,检查程序是否有内存泄漏、及上面提到的内在错误。内存检查工具很多,比如我的前面帖子里介绍的linux系统下的valgrind。

你可能感兴趣的:(内存泄漏及管理--程序开发注意的问题)