C++内存管理

内存布局

      C++的内存分为5大区,按照地址从高位到低位的顺序,分别为栈区,堆区,BBS区,数据区,代码区。

栈区

     编译器自动管理分配,存放程序中的局部变量,函数参数值,返回变量。内存分配从高地址向低地址增长。

堆区

     程序中用户自定义动态分配的内存区域,内存分配从低地址向高地址增长。

BBS区

     存放程序中被显示初始化为0的全局变量和静态变量;以及未被初始化的全局变量和静态变量。

数据区

     存放已初始化的全局变量,静态变量,常量数据(如字符串常量)。

代码区

     存放可执行程序的机器码。

下图是内存布局的基本结构

C++内存布局

函数栈

       如上图所示,可执行程序文件包含BBS,数据区和代码区,可执行程序载入内存后系统会保留一些空间,堆区和栈区。堆区主要是动态分配的内存(默认情况下),而栈区主要是函数以及局部变量等。

当调用函数时,一块连续内存压入栈;函数返回时,堆栈帧弹出。

堆栈帧包含如下数据:

1).函数返回地址

2).局部变量/CPU寄存器数据备份

以main调用fa(),fa调用fb(),来举例说明函数调用压栈过程,如下图所示:

调用进栈

函数调用结束后会依次出栈,如下图所示:

出栈

全局变量

      当全局变量,静态变量未被初始化的时候,他们记录在BBS段。

       处于BBS段的变量值默认为0,考虑到这一点,BBS段内部无需存储大量的零值,只需记录字节个数即可。BBS段主要是为了节省可执行文件在磁盘上所占空间,它只记录变量所需的大小。对未初始化的大型数组的节省效率比较明显,举例如下:

d

在上述程序中,若不存在BBS段,可执行文件将开辟10000*sizeof(int)大小的空间,并全部存储为0,该变量将在磁盘上占用39KB的空间,但是若存在BBS段,则在可执行文件中,将只是记录现在BBS段总大小40000即可,无需占据39KB的空间。

系统载入可执行程序后,将BBS段的数据载入数据段,并将内存初始化为0,再调用程序入口main函数。

内存对齐

      对于基本类型,如float,double,int,char等,他们的大小和内存占用是一致的。但是对于结构体而言,我们取得其sizeof的结果,会发现这个值可能会大于结构体成员大小的总和,这是由于结构体内部成员进行了内存对齐。

     进行内存对齐有2个好处:

    1).内存对齐使数据读取更高效

      在硬件设计中,数据读取的处理器只能从地址为k的倍数内存处开始读取数据,这种读取方式相当于将内存分为多个块,如果内存可以从任意位置开始存放的话,数据很可能会被分散到多个块中,处理分散在多个块中的数据需要移除首位不需要的字节,然后进行合并,非常耗时。为了提高数据的读取效率,程序分配的内存不是连续存储的,而是按首地址为k的倍数方式存储,这样就可以一次性读取数据,而不需要额外的操作。

   2).在某些平台上,不进行内存对齐会崩溃 

      不是所有的硬件平台CPU都能访问任意地址上的数据,某些硬件平台只能在某些地址处取得特定类型数据,否则会抛出硬件异常。

内存对齐规则

       定义有效对齐值为结构体中最宽成员和编译器/用户指定对齐值中较小的那个。

1).结构体起始地址为有效对齐值的整数倍

2).结构体总大小为有效对齐值得整数倍

3).结构体第一个成员偏移值为0,之后成员的偏移值为min(有效对齐值,自身大小)的整数倍。

相当于每个成员要进行对齐,并且每个结构体也要进行对齐。

内存碎片

       程序的内存往往不是紧凑连续排布的,而是存在着许多碎片。我们跟据碎片的原因把碎片分为内部碎片和外部碎片两张类型:

1).内部碎片:系统分配的内存大于实际所需的内存(内存对齐机制)

2).外部碎片:不断分配回收不同大小的内存,由于内存分布散乱,较大内存无法分配。

继承类布局

      继承

      如果一个类继承自另一个类,那么它自身数据位于父类之后。

      含虚函数的类

      如果当前类包含虚函数,则会在类的最前端占用4个字节,用于存储虚表指针,它指向一个虚函数表, 虚函数表中包含当前类的所有虚函数指针。

      虚函数表   下一章详细讲解。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 内存管理是C++最令人头痛的问题,也是C++最有争议的地方。C++高手从中获得了更好的性能,更大的自由,C++菜鸟...
    Codeapes阅读 447评论 0 2
  • C++内存分区 C++存在如下的内存分区 1)栈区(stack):由编译器自动分配释放 ,存放函数的 参数值,局部...
    VictorHong阅读 615评论 1 0
  • 内存分配方式 在C++中,内存分成5个区,他们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。 在栈上创建...
    showaichuan阅读 349评论 0 2
  • 简介 在C++中,内存分成5个区,他们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。栈:在执行函数时,函...
    analanxingde阅读 285评论 0 1
  • 1、内存分配方式 在C++中,内存分为5个区,分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。 堆:new...
    星期八我一定好好读书阅读 187评论 0 0

友情链接更多精彩内容