文章目录
本文来源《高质量C++编程》第7章
内存分配方式
- 从静态数据(.data)存储区域分配
1.在程序编译时就已经分配好
2.在程序整个运行期间都存在
3.全局变量,static变量
- 在栈上创建
1.局部变量
2.函数结束时存储单元自动释放
3.效率高,但分配内存容量有限
- 从堆上分配(动态内存分配)
1.malloc,new申请
2.动态内存生存期由程序员决定,使用灵活
内存空间的分布
1.text区域:程序代码段,只读
2.data区域:全局数据段,存储静态变量和已经初始化的全局变量
3.BSS区域:未初始化数据段,存储未初始化的全局变量和静态局部变量
4.堆区域:new malloc动态申请内存区域
5.mmap内存映射区域:动态连接so库代码段、数据段、未初始化数据段 的区域
6.stack区域:局部变量和函数调用栈区域,执行完后会自动释放
堆与栈的区别
区别 | 栈 | 堆 |
---|---|---|
管理方式不同。 | 栈由操作系统自动分配释放,从右向左入栈; | 堆的申请和释放由程序员控制,易发生内存泄漏 |
空间大小不同。 | 栈大小要远远小于堆大小,栈大小默认为1M, | 堆大小默认为3G |
生长方向不同。 | 栈向下生长,内存地址由高到低,是一块连续的内存区域 | 堆向上生长,内存地址由低到高,是不连续的内存区域; |
分配方式不同。 | 栈有 2 种分配方式:静态分配和动态分配。静态分配是由操作系统完成的,比如局部变量的分配。动态分配由alloc()函数分配,但是栈的动态分配和堆是不同的,它的动态分配是由操作系统进行释放,无需我们手工实现。 | 堆都是动态分配,malloc,new。 |
分配效率不同。 | 栈由操作系统自动分配,会在硬件层级对栈提供支持,分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。 | 堆则是由C/C++提供的库函数或运算符来完成申请与管理,实现机制较为复杂,频繁的内存申请容易产生内存碎片。显然,堆的效率比栈要低得多。 |
存储内容。 | 栈:在函数调用时,1主函数中的下一条指令->2函数参数->局部变量;调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址(主函数的下一条指令)程序由该点继续运行 | 堆:堆的头部用一个字节存放堆的大小 |
碎片问题。 | 栈是采用先进后出的方,不会出现碎片化问题 | 堆在不断地执行new和delete的操作中,内存逐渐被碎片化,使得程序执行效率变低, |
内存分配可能出现的问题
问题 | 原因 | 解决方案 |
---|---|---|
内存分配未成功,但却使用了它 | 系统分配内存不一定会成功 | malloc,new申请内存之后,需要立即检查指针值是否为NULL,防止使用指针值为NULL的内存。函数参数:assert(p!=NULL),申请的内存:if(p!=NULL) |
内存分配成功但未经初始化就使用了它 | 开发人员可能会误认为内存的缺省时初值为0,引用初值错误 | 不要忘记为数组和动态内存赋初值,防止将未被初始化的内存作为右值引用 |
内存分配成功后,忘记释放内存 | 没有释放成功分配的内存 |