c++内存泄漏方面的知识

内存泄漏和内存溢出

内存溢出 out of memory:是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。
内存泄露 memory leak:是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。
memory leak会最终会导致out of memory!

常见的内存错误

  1. 内存申请未成功但是使用了它,产生原因:
    这是编程新手常犯这种错误,因为他们没有意识到内存分配会不成功。
    解决方法

    在使用内存时候记得进行null判断
    如果指针 p 是函数的参数,那么在函数的入口 处用 assert(p!=NULL)进行检查。
    如果是malloc和new申请的内存记得进行(p!=null)或者(p==null)判断

  2. 内存分配虽然成功,但是尚未初始化就引用它,犯这种错误主要有两个起因:
    一是没有初始化的观念。
    二是误以为内存的缺省初值 全为零,导致引用初值错误(例如数组)。
    解决方法

    内存的缺省初值究竟是什么并没有统一的标准,尽管有些时候为零值,我们宁可信其无不可信其有。如果定义的是数组的话,可以这样初始化: int a[10] = {0}; 或者用memset 函数来初始化 memset(a,0,sizeof(a))

  3. 内存分配成功并且已经初始化,但操作越过了内存的边界,产生原因:
    使用数组时经常发生下标“多 1”或者“少 1”的操作
    解决方法

    在使用for循环,或者有边界的操作的时候一定要注意边界处理

  4. 忘记了释放内存,造成内存泄露,产生原因:
    含有这种错误的函数每被调用一次就丢失一块内存。
    刚开始时系统的内存充足,你 看不到错误。
    终有一次程序突然死掉,系统出现提示:内存耗尽。
    这种情况在一个函数里面中间进行了return操作,然后在return之前申请了内存,但是没有释放发生的情况很多比如这样:

      void Func(void)
    {
       char *p = new char[10];  
       ......  
       if(某个条件)
       {
       		return; //在此处直接return 并没有调用delete p 造成内存泄漏
       }
       ......
    

解决方法
> 动态内存的申请与释放必须配对,程序中 malloc 与 free 的使用次数一定要相同,否 则肯定有错误(new/delete 同理)。

  1. 释放了内存却继续使用它,产生原因:
    一是程序中的对象调用关系过于复杂,实在难以搞清楚某个对象究竟是否已经释放了内 存,此时应该重新设计数据结构,从根本上解决对象管理的混乱局面。
    二是return 返回了指向栈空间的指针或者引用举个例子(下面是返回的指针,引用类似):

    此处返回了栈空间的指针,如果对外调用者使用了,会造成不可预估的情况
    char *Func(void)
    {
       char str[]="hello world"; //str数组创建在函数堆栈上,并用字符串常量来初始化
       ......
       return str; //该句存在隐患,str指向的内存单元将被释放
    
    这种虽然使用时候没有什么问题是在程序的静态数据区但是这种东西一直存在,设计上感觉还是有问题
    const char *Func(void)
    {
       (const)char *pStr="hello world";  //字符串常量存放在程序的静态数据区,
        //pStr指针虽然是在栈上定义的,但当函数返回时,它指向的那个内存地址,也就是字符串"hello world"还是存在的,并没有被释放
        return pStr;  //返回字符串常量的地址,没有问题
    }
    

    三是使用 free 或 delete 释放了内存后,没有将指针设置为 NULL。导致产生“野指针”。

自己写代码检测泄漏方法

重载new/delete操作符
重载new/delete操作符,用list或者map记录对内存的使用情况。new一次,保存一个节点,delete一次,就删除节点。
最后检测容器里是否还有节点,如果有节点就是有泄漏。也可以记录下哪一行代码分配的内存被泄漏。
类似的方法:在每次调用new时加个打印,每次调用delete时也加个打印。

检查内存泄漏工具

valgrind工具
工具检测原理
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C 内存管理是指在编程过程中,对内存资源的分配和释放进行管理的技术。在C语言中,程序员需要手动管理内存的分配和释放,以便有效地使用系统的内存资源。 C语言中的内存管理主要包括以下几个方面: 1. 内存的分配:C语言中使用malloc()函数来分配堆内存。该函数接收一个整数参数,表示要分配的字节数。分配的内存块是在程序运行时动态分配的,并且在堆区中。分配完成后,malloc()函数会返回一个指向分配内存块起始位置的指针。 2. 内存的释放:C语言中使用free()函数来释放之前分配的内存。释放内存的操作是手动进行的,当不再需要使用之前分配的内存块时,程序员需要显式调用free()函数来释放该内存块。释放内存后,该内存块将被系统回收,可以被其他程序使用。 3. 内存泄漏:在使用malloc()函数分配内存后,如果程序员忘记调用free()函数来释放内存,就会导致内存泄漏内存泄漏会导致程序运行过程中逐渐占用更多的内存,最终耗尽系统的内存资源,导致程序崩溃。 4. 指针和数组:C语言中的指针与数组密切相关。指针是变量,保存了内存地址。数组也是一种特殊的指针,指向一段连续的内存空间。程序员可以通过指针和数组操作内存,实现数据的动态存储和访问。 5. 内存的动态分配:C语言中,动态分配内存可以根据程序运行时的需要,动态地调整内存的大小。例如,在需要存储不确定数量的数据时,可以使用realloc()函数重新调整之前分配的内存大小。 总之,C语言中的内存管理是程序员需要关注的重要问题。合理地进行内存的分配和释放,可以避免内存泄漏和内存溢出等问题,提高程序的效率和稳定性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值