c++程序内存布局以及堆栈概念详解

本文详细介绍了C/C++程序运行时的内存分布,包括1G内核空间与3G用户空间的划分,以及用户空间中的栈区、堆区、内存映射段、数据段、bss段和代码段的具体作用。栈区用于存放函数局部变量、参数和返回值,堆区由用户通过malloc等函数动态管理。数据段和bss段分别存放已初始化和未初始化的全局变量,代码段则包含可执行代码和只读常量。理解这些内存布局有助于优化程序和避免内存问题。
摘要由CSDN通过智能技术生成

前言:

下图是c/c++的进程的内存分布布局图,搞清楚内存布局对于理解一个程序是非常重要的。


  一个程序运行起来,操作系统会给每个进程分配一个 4G 的程序地址空间,当然这都是虚拟地址空间,因为如果一个进程分 4G 的内存,那么就算有再多的内存也不够分。


   这些虚拟地址空间中的内存分段都是什么意思呢?下面进行讲解(linux系统为1G和3Gwindows系统为2G和2G):

在这里插入图片描述

一、首先进程地址空间的 1G(windows系统为2G) 内核空间是给操作系统使用的,我们用户是没有操作权限的。


二、剩下的 3G(windows系统为2G) 内存空间中,分为了栈区、内存映射段、堆区、数据段、bss段、代码段


1、栈区

(1)这里的栈和数据结构的栈并不相同,数据结构的栈是一种后进先出的数据结构,而内存划分的栈是操作系统按照栈的特性,给用户划分出的内存区间。


(2)栈区一般存放:函数体的局部变量、函数调用期间的所有参数压栈、函数的返回值注意栈区这段内存是由操作系统自己维护的,所以函数结束,在栈上的空间会由操作系统自己回收。

(3)32位应用程序(使用32位编译器编译),栈的默认内存大小一般为1M或者2M,64位应用程序(使用64位编译器编译)栈内存一般为4M,windows系统可以在GCC编译器编译前指定gcc 参数,修改默认栈大小

gcc -Wl,--stack=size

具体修改不同平台的栈内存,请拜读朕的另外一篇博客

https://blog.csdn.net/xujianjun229/article/details/120237390

(4)windows32位系统,一个进程所能使用的最大虚拟内存为2G,而一个线程的默认线程栈StackSize为1024K(1M),这样当线程数量逼近2000时,2000*1024K=2G(大约),内存资源就相当于耗尽。

2、堆区

(1)用户所操作的内存就是堆上的空间

(2)用户可以使用 malloc / calloc / realloc / new 申请堆上的空间,但是用户申请堆上的空间必须自己手动释放(free或者delete),不然会造成内存泄漏。

3、内存映射段

(1)存放 动态库 / 静态库,以及文件映射,匿名映射等等一切有依赖性的东西都在这段区域


4、数据段

(1)存放全局变量、静态类型的变量。

(2)当代码编译完后,在可执行程序这个文件中(二进制文件)已经把这些数据的空间划分好了,这种类型的数据,在程序运行以前,操作系统就将数据段中的数据加载到内存了。也就是说在进入 main 函数之前这些数据已经划分好空间了。

5、bss段

(1)其实在 C 语言中,数据段中还有一个 bss 段,这里面存放的是未初始化的全局变量和静态数据,而数据段中存放的是已经初始化过的全局变量和静态数据。

(2)数据段中的所有数据已经划分好空间了,但是 bss 段并没有给其中的数据划分空间。

6、代码段

(1)存放可执行代码,以及只读常量(字符串常量等等)。这段内存是只读的。
 

三、总结:一个程序本质上都是由栈区、内存映射段、堆区、数据段、bss段、代码段组成的

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值