C++ 内存分布
一个程序的section, 从低地址到高地址,一个程序由代码段、数据段、BSS段、堆、共享区、栈等组成。
在C++中,内存分成5个区:堆、栈、自由存储区、全局/静态存储区和代码段。
栈 stack ,存储局部变量、函数参数值。函数执行结束时这些存储单元自动被释放。栈从高地址向低地址增长。是一块连续的空间。
堆 heap,就是由malloc分配的内存块,一个malloc就必须要对应一个free。堆从低地址向高地址增长。
自由存储区,由new等分配的内存块,通过delete来释放空间
全局/静态存储区,全局变量和静态变量被分配到同一块内存中
代码段,存放的是可执行的代码。只读,代码段的头部还会包含一些只读的常数变量。
自由存储区与堆有什么区别?
很多人会说,malloc在堆上分配的内存块,使用free释放内存,而new所申请的内存则是在自由存储区上,使用delete来释放。
也有很多人说,很多编译器的new/delete都是以malloc/free为基础来实现的,所以通过new 申请的内存,难道不在堆上吗?
而实际上,堆是操作系统维护的一块内存,而自由存储是C++中通过new与delete动态分配和释放对象的抽象概念。堆与自由存储区并不等价
具体来说就是,堆(heap)是C语言和操作系统的术语。堆是操作系统所维护的一块特殊内存,它提供了动态分配的功能。而自由存储是C++中通过new和delete动态分配和释放对象的抽象概念,通过new来申请的内存区域可称为自由存储区。
基本上,所有的C++编译器默认使用堆来实现自由存储,也即是缺省的全局运算符new和delete也许会按照malloc和free的方式来被实现,这时藉由new运算符分配的对象,说它在堆上也对,说它在自由存储区上也正确。
但我们可以通过重载操作符,改用其他内存来实现自由存储,例如全局变量做的对象池,这时自由存储区就区别于堆了。
常见的内存错误及其对策
-
内存分配未成功,却使用了该指针
定义指针时,先初始化为
nullptr
再申请;申请内存之后,应检查指针值是否为nullptr
再使用 -
内存分配成功,但尚未初始化就引用
为数组和动态内存赋初值
-
内存分配成功并且已经初始化,但操作越过了内存的边界
操作时进行下标越界判断
-
忘记了释放内存,造成内存泄露;或者释放了内存仍继续使用它。
使用RAII 资源操作指针,或者使用智能指针,释放后的指针立即置为
nullptr
,防止野指针
Reference
欢迎关注公众号【三戒纪元】