C++内存管理问题

C++内存管理问题:

栈溢出情况:

栈内存分配:

栈,在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。

只有在栈空间大于申请的空间时,系统才会为程序提供内存,不然就出现栈溢出的情况,即出现overflow的问题。

堆溢出情况:

堆内存分配:

堆,就是那些由malloc分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个malloc就要对应一个free。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。new和delete分配的内存是在自由存储区中,一般自由存储区是由堆来实现的。

如果不停地申请空间而没有用delete来释放空间,会造成内存不停增长,即发生内存泄漏

堆和栈的区别:

  • 管理方式不同:对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制,容易产生memory leak(内存泄漏)。

  • 空间大小:对于堆内存,一般在32位系统下可以达到4G,近乎没有限制;对于栈而言,一般都是有空间大小限制的。

  • 碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。而因为栈是先进后出的队列,所以栈不存在空间碎片的问题。

  • 生长方向:对于堆来讲,生长方向是向上的,也就是向着内存地址增加的方向;对于栈来讲,它的生长方向是向下的,是向着内存地址减小的方向增长。

  • 分配方式:堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。

  • 分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会分到足够大小的内存,然后进行返回。显然,堆的效率比栈要低得多。

内存分配的常见错误及对策

  • 内存未分配成功却使用了它

    在使用内存之前检查指针是否为NULL。如果指针p是函数的参数,那么在函数的入口处用assert(p!=NULL)进行检查。如果是用malloc或new来申请内存,应该用if(p==NULL) 或if(p!=NULL)进行防错处理。

  • 内存分配成功后未初始化就使用

    原因:1.没有初始化的概念;2.误以为内存缺省值全为0,导致引用初始值错语。 解决方案:使用前先初始化

  • 内存分配成功且初始化,但越界

  • 用完的内存未释放,造成内存泄漏

    申请的内存在用完后不释放,会导致内存逐步变小,最终使得内存耗尽,导致程序崩溃。动态内存的申请与释放必须配对使用,malloc和free使用的次数要相同,new和delete也一样,否则必然会存在错误。

  • 内存释放后继续使用(野指针)

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

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

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

有了malloc/free后为何还需要new/delete

malloc和free是C/C++标准库函数,new和delete是c++运算符,都是用来内存的动态申请和释放的。

对于非内部数据类型对象而言,光用malloc和delete无法满足动态对象的要求。对象在创建的同时需要自动执行构造函数,而对象在消亡之前需要自动执行析构函数。而由于malloc和free是库函数而不是运算符,编译器没有权限,不能把执行构造函数和析构函数的任务强加于malloc和free。对于内部数据类型而言,两者是等价的。

new和delete不是库函数,是运算符。

new和malloc内存分配失败后的区别

  • new分配内存失败后会抛出异常,当new不能分配足够的内存时,默认动作是抛出bad_alloc异常。

  • malloc内存分配失败时不会抛出异常,只会返回一个NULL值。

[参考](https://www.cnblogs.com/findumars/p/5180490.html)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值