C程序中的内存分布
一个典型的C程序存储分区包含以下几类:
- Text段
- 已初始化数据段
- 未初始化数据段
- 栈
- 堆

进程运行时的典型内存布局
1. Text段
Text段通常也称为代码段,由可执行指令构成,是程序在目标文件或内存中的一部分,Text段通常放在栈或堆的下面,以防止堆栈溢出篡改其数据。
通常情况下,Text段是可共享的,对于需要频繁调用的程序,其在内存中只需要一份拷贝即可,如文本编辑器、C编译器、Shell等,因此text段通常设为只读以防止程序的突发性的修改。
2. 已初始化数据段
已初始化数据段,通常简单称作数据段,数据段占据程序虚拟地址空间的一部分,内部包括全局变量、静态变量(程序负责初始化这些变量)。需注意的是,数据段不是只读的,在运行时变量值是可以变动的。
数据段还可以更细的分为初始化只读区以及初始化可读写区。
举例:全局字符串 char s[] = “hello world”,全局变量 int debug=1,静态变量 static int i = 10 存储在初始化可读写区;另一种情况下,const char* string = “hello world”,字符串“hello world”存储在初始化只读区,string指针则存在初始化可读写区。
3. 未初始化数据段
未初始化数据段,通常称作“bss”段,名字来源于古老的汇编操作符命名 “block started by symbol”,段内的数据在程序开始执行之前被内核初始化为0值,通常开始于已初始化数据段的末尾处。段内包含初始化为0的全局变量/静态变量以及源码中未显示进行初始化的变量。
举例:变量 static int i; 全局变量 int j; 包含在BBS段中。
4. 栈
栈与堆是相互毗邻的,并且生长方向相反;当栈指针触及到堆指针位置,意味着栈空间已经被耗尽(如今地址空间越来越大,及虚拟内存技术发展,栈与堆可能放置在内存的任何地方,但生长方向依然还是相向的)。
栈区域包含一个LIFO结构的程序栈,其通常放置在内存的高地址处,在x86架构中,栈朝地址0方向生长,在其它架构也可能朝着相反的方向生长。栈指针寄存器跟踪栈顶位置,每当有数值被压入栈中,栈顶指针会被调整,在一个函数的调用过程中,压入的一系列数值被称作“栈帧”,栈帧至少包含一个返回地址。
栈存储着自动变量以及每次函数调用时保存的信息,每当函数被调用时,返回地址以及调用者的上下文环境例如一些机器寄存器都存储在栈中,新的被调用函数此时会在栈上重新分配自动/临时变量,这就是递归函数的工作原理。每当函数递归调用自己时,都会使用新的栈帧,因此当前函数实体内的栈帧内的变量不会影响另外一个函数实体内的变量。
5. 堆
堆通常用作动态内存分配,堆空间起始于BSS段的末尾,并向高地址处生长,堆空间通常由malloc, realloc 及 free管理,这些接口可能再使用brk/sbrk系统调用来调整大小,在一个进程中,堆空间被进程内所有的共享库及动态加载模块所共享。
示例-查看可执行文件的存储分配
注:size命令以字节为单位统计可执行程序的text, data, 及bss段(更多详情参考man page of size(1))
1. 检查下述C程序

编译后查看text/data/bss分布情况

2. 增加一个全局变量

编译后观察变化,bss区域增加了4字节

3. 再添加一个静态变量

编译后再看变化,bss区域增加了4字节

4. 初始化3中的静态变量看看

此时变量存储到了data段,data增加了4字节,bss减少了4字节

5.继续初始化2中的全局变量看看

此时静态变量也存储到了data段,data增加了4字节,bss减少了4字节

6. 添加一个全局const变量看看

此时“haha”字符串存储到了text段,并增加了5个字符,多出来的一个字符是\0,ptr指针存储到了data段,增加了4个字节。

注:在步骤4/5中,初始化的值若为0,编译器还是会将变量放入BSS区。感兴趣的同学可以动手编译看看。
文章翻译/修改自 https://www.geeksforgeeks.org/memory-layout-of-c-program/
C程序中的内存分布的更多相关文章
- 了解 JavaScript 应用程序中的内存泄漏
简介 当处理 JavaScript 这样的脚本语言时,很容易忘记每个对象.类.字符串.数字和方法都需要分配和保留内存.语言和运行时的垃圾回收器隐藏了内存分配和释放的具体细节. 许多功能无需考虑内存管理 ...
- [转载]Java应用程序中的内存泄漏及内存管理
近期发现测试的项目中有JAVA内存泄露的现象.虽然JAVA有垃圾回收的机制,但是如果不及时释放引用就会发生内存泄露现象.在实际工作中我们使用Jprofiler调用java自带的 jmap来做检测还是很 ...
- 高效使用 JavaScript 闭包,避免 Node.js 应用程序中的内存泄漏
在 Node.js 中,广泛采用不同形式的闭包来支持 Node 的异步和事件驱动编程模型.通过很好地理解闭包,您可以确保所开发应用程序的功能正确性.稳定性和可伸缩性. 闭包是一种将数据与处理数据的代码 ...
- [Swift通天遁地]七、数据与安全-(11)如何检测应用程序中的内存泄露
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...
- (二)程序中的内存&&栈
一.程序运行为什么需要内存?基本概念? 内存是程序运行的立足之地,程序需要用内存来存储一些变量. 内存管理最终是由操作系统完成的,内存在本质上是一个硬件器件,由硬件系统提供:内存由操作系统统一管理,为 ...
- iOS程序中的内存分配 栈区堆区全局区
在计算机系统中,运行的应用程序的数据都是保存在内存中的,不同类型的数据,保存的内存区域不同.一.内存分区 栈区(stack) 由编译器自动分配并释放,存放函数的参数值,局部变量等.栈是系统数据结构,对 ...
- _CrtDumpMemoryLeaks报告程序中的内存泄露问题(简单示例代码)
// .h 文件 #pragma once class CConsoleDump { public: explicit CConsoleDump(LPCTSTR lpszWindowTitle = N ...
- 如何使用 VLD 检测程序中的内存泄漏?
下载地址:https://kinddragon.github.io/vld/ 下载 windows 安装包,进行安装即可,它会给你设置好 vs 的环境变量,使用时,直接在 vs ide 中包含即可. ...
- Linux下几款C++程序中的内存泄露检查工具
https://blog.csdn.net/gatieme/article/details/51959654
随机推荐
- CentOS7 安装Redis和PHP-redis扩展
aemonize yes Redis是一个key-value存储系统,属于我们常说的NoSQL.它遵守BSD协议.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的AP ...
- [ ceph ] 基本概念、原理、架构介绍
1. Ceph 架构 1.1 Ceph 接口 Ceph 支持三种接口: Object:有原生的API,而且也兼容 Swift 和 S3 的 API Block:支持精简配置.快照.克隆 File:Po ...
- web page popup window model
jQuery UI dialog: https://jqueryui.com/dialog/ Semantic UI https://semantic-ui.com/modules/modal.htm ...
- WebGL学习笔记二——绘制基本图元
webGL的基本图元点.线.三角形 gl.drawArrays(mode, first,count) first,代表从第几个点开始绘制即顶点的起始位置 count,代表绘制的点的数量. mode,代 ...
- [转] spring-boot集成swagger2
经测,spring-boot版本使用1.5.2+时需使用springfox-swagger2版本2.5+(spring-boot 1.2 + springfox-swagger2 2.2 在未扫描ja ...
- git 删除本地分支,删除远程分支
本地分支 git branch -d 分支名 远程分支 git push origin --delete 分支名 查看所有分支 git branch -a
- Codeforces Round #604
Beautiful Regional Contest 题意 题解 代码 Beautiful Sequence 题意 题解 代码 一个思路不够清晰的代码 Beautiful Mirrors with q ...
- Word 频繁无响应
可以参考以下方法,这是我的解决办法,不保证对你也有用. 步骤一: 在「开始 > 运行」中输入「winword /a」进入无加载项 Word: 依次进入「Word 选项 > 高级 > ...
- Word 查找替换高级玩法系列之 -- 通配符大全B篇
未完 ...... 点击访问原文(进入后根据右侧标签,快速定位到本文)
- C++自主测试题目
下面是题目 后面有代码 1.键盘输入3个整数a,b,c值,求一元二次方程a*X∧2+b*X+c=0(a≠0)的根,结果保留两位小树. 2.编写一个口令输入程序,让用户不停输入口令,直到输对为止,假设口 ...