C语言 内存布局学习总结

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/CV_Jason/article/details/82120255

前言

  C语言的内存布局对于理解C语言类型的作用域和声明周期,以及C语言对操作系统资源的使用规则至关重要,因此,理解C语言的内存布局模型,有助于深入理解C语言编程思想,以及高屋建瓴的学习C++内存布局模型。
  但实际上,C语言的内存布局,要比我们想象中的复杂,根据不同的阶段有不同的分布,但作为一个程序员,我们仅关心在C语言编译和运行时内存的分布和管理,对于更底层的知识点,暂且不做梳理(其实更重要)。
  本文是对C语言内存布局的学习总结,C++的对象内存模型会有所不同,但是对于内置数据类型,C和C++是完全一样的。看了许多大神的帖子(参考链接中已列出),写的都很不错,我做了一下归纳和总结,可能会有不严谨的地方,还请各位大佬不吝赐教。


C语言内存布局

  我们知道,C语言从源代码到可执行程序,大约需要编译->汇编->链接三个阶段。按照这个阶段划分,C语言的内存管理,可以分为静态区域动态区域

这里写图片描述

静态区域

  全局变量和静态变量的存储是放一块的,初始化的全局变量和静态变量在一块区域(读写数据段),未初始化的全局变量和静态变量在另一段(BSS段),程序结束后由系统释放。

  • 代码段
      通常是指用来存放程序中未初始化的全局变量的一块内存区域。BSS是英文Block Started by Symbol的简称。BSS段属于静态内存分配。
  • 数据段
      分为只读数据段(RO data,即常量区)和读写数据段(RW data),其中RO区域用于存放不会更改的数据,比如字符串常量,而RW区域存放程序中已初始化的数据。数据段属于静态内存分配。
  • BSS段
      通常是指用来存放程序中未初始化的全局变量的一块内存区域。BSS是英文Block Started by Symbol的简称。BSS段属于静态内存分配。

动态区域

  堆和栈只在运行时出现,因此,我们可以称之为内存的动态区域。

  • 堆区(heap)
      堆内存只在运行时出现。一般由程序员分配和释放,比如malloc/free函数动态分配和回收内存。如果程序没有释放,则有操作系统来回收,内存分配的结构类似于一个链表。
  • 栈区(stack)
      栈内存只在程序运行时出现,一般由编译器自动分配和控制,比如说局部变量、函数参数以及返回值使用的栈空间等。

总结

  代码段、数据段、BSS段在程序链接后立即产生,存在于程序的可自行文件中,属于静态区域,但是未初始化数据在程序初始化阶段开辟,放在BSS段中。堆和栈在程序运行期间进行动态的分配和释放,是一种动态过程,因此属于动态区域。

这里写图片描述
  一个可执行程序分为映像运行两种状态——
  在编译链接后的映像中,将只包含代码段、数据段(包括RO和RW段);
  在程序运行之前,会有个加载过程,该过程为未初始化的全局变量和静态变量分配内存,生成BSS段;
  而在程序开始运行之后,根据程序需要,自动的进行内存分配和回收,都发生在堆栈上。
  在操作系统中,程序的运行依赖进程,本质上讲,C语言的内存分布模型,底层上,其实还是进程对内存资源的管理,或者说是操作系统对于进程资源调度和分配的策略。
  因此,程序中的几个段,在最终的运行阶段,转化为进程内存管理的几个区,在进程的内存管理中,从低地址向高地址,依次是只读区(和上文的RO data不同)、读写区、未初始化代码段、堆和栈。其中只读区包含代码段(code)和只读数据段(RO data)。
  在映像文件中,将包含代码段(Code)、只读数据段(RO data)和数据读写段(RW data),未初始化的数据段(BSS)在程序初始化时加载开辟,堆和栈在程序运行期间动态开辟,其中,堆和栈一般是相向扩展的。


参考链接

[1].C和C++内存模型 http://www.cnblogs.com/zhangsf/p/3835033.html
[2].C语言的代码内存布局具体解释 https://www.cnblogs.com/mfmdaoyou/p/6792665.html
[3]. (深入理解计算机系统) bss段,data段、text段、堆(heap)和栈(stack) https://www.cnblogs.com/yanghong-hnu/p/4705755.html

展开阅读全文

没有更多推荐了,返回首页