堆栈,数据,文本,heap,bss,text data,stack
text data bss stack heap 段
根据APUE,程序分为下面的段:.text, data (initialized), bss, stack, heap。
data/bss/text:
text段在内存中被映射为只读,但.data和.bss是可写的。
bss是英文Block Started by Symbol的简称,通常是指用来存放程序中未初始化的全局变量的一块内存区域,在程序载入时由内核清0。BSS段属于静态内存分配。初始值也是由用户自己定义的连接定位文件所确定,用户应该将定义在可读写的RAM区内,源程序中使用malloc分配的内存就是这一块,不是根据data大小确定,主要由程序中同时分配内存最大值所确定,不过如果超出了范围,也就是分配失败,可以等空间释放之后再分配。
text段是程序代码段,在AT91库中是表示程序段的大小,是由编译器在编译连接时自动计算的,当你在链接定位文件中将该符号放置在代码段后,那么该符号表示的值就是代码段大小,编译连接时,该符号所代表的值会自动代入到源程序中。
data包含静态初始化的数据,所以有初值的全局变量和static变量在data区。段的起始位置也是由连接定位文件所确定,大小在编译连接时自动分配,与程序大小没有关系,但和程序使用到的全局变量,常量数量相关。
stack/heap:
栈(stack)保存函数的局部变量和参数。是一种“后进先出”(Last In First Out,LIFO)的数据结构,这意味着最后放到栈上的数据,将会是第一个从栈上移走的数据。对于哪些暂时存贮的信息,和不需要长时间保存的信息来说,LIFO这种数据结构非常理想。在调用函数或过程后,系统通常会清除栈上保存的局部变量、函数调用信息及其它的信息。栈另外一个重要的特征是,地址空间“向下减少”,即当栈上保存的数据越多,栈的地址就越低。栈(stack)的顶部在可读写的RAM区的最后。
堆(heap)保存函数内部动态分配内存,是另外一种用来保存程序信息的数据结构,更准确的说是保存程序的动态变量。堆是“先进先出”(First In first Out,FIFO)数据结构。只允许在堆的一端插入数据,在另一端移走数据。堆的地址空间“向上增加”,即当堆上保存的数据越多,堆的地址就越高。
在程序中的存储详情如下:
char *string = “Hello World”;
int iSize;
char *fun(void)
{
char *p;
iSize = 8;
p = malloc(iSize);
return p;
}
存放的位置

Text段:上面标记为红色的部分(还包括整个fun函数,由于下边需要,所以没有标记)都存放在Text段,Text段用来存放代码(二进制文件)和常量,该段的数据通常是只读的
例:
Text段:上面标记为红色的部分(还包括整个fun函数,由于下边需要,所以没有标记)都存放在Text段,Text段用来存放代码(二进制文件)和常量,该段的数据通常是只读的
例:

  1. char *p = “Hello”;

  2. p[0] = ‘a’;
    VC6.0下,编译无错,但运行是提示内存不可写,这就是因为"Hello"存放在Text段,是只读的,你不能去修改.
    Data段: 已经初始化了的全局变量string就存放在该段,Data段用来存放初始化了的变量,即初始化了的全局变量和静态变量
    BSS段: 未初始化的全局变量iSize存放在这,BSS段主要存放在未初始化的变量,即未初始化的全局变量和静态变量
    Heap段: 程序员手动分配的malloc(iSize)这篇内存存放在该段,也需要用户自行释放
    Stack段:函数里的局部变量*p存放在该段,Stack段主要存放局部变量、临时变量、函数相互调用的返回的地址,该段由编译器自行分配和释放
    接下来来看看,什么被分配了内存,什么时候释放内存:
    全局变量和静态变量:程序开始的时候就分配了,程序结束时候释放内存。
    局部变量:函数调用的时候为变量分配内存,调用结束释放内存。
    堆里的:调用malloc时分配内存,调用free时释放。
    .text .data .bss .stack .heap 详解
    .text 代码段:用来存放代码和常量(const 关键字定义的变量)。
    .data 数据段:用来存放有初始值的全局变量、全部静态变量(static 关键字定义的变量)。注意全部静态变量包括全局静态变量和局部静态变量,并且不论这些变量是否有初始值。即不管有没有初始值,也不管是全局变量还是定义在函数内的局部变量,只要是用 static 关键字定义的变量,都放在 .data 数据段内。
    .bss BSS段:用来存放没有初始值的全局变量。(没有初始值的局部变量好像也存在这里,网上验证帖子,待验证)。
    .stack 栈区: 用来存放局部变量,函数的参数,返回值等,由编译器自动分配释放。如一个函数被调用后,产生的临时变量都会存到栈区的顶部,当函数完成后,会自动从顶部将刚使用的数据销毁。栈区的地址是从高地址向下增长的。
    .heap 堆区: 用来动态内存分配,如 malloc, new 申请的内存,由程序员手动分配释放。程序中不释放,则程序结束时,由OS回收;据说这个和数据结构中的堆 没有什么关系;堆区使用时地址向上增长。
    以上5段,在生成的 hex 文件中是怎么分配呢?
    Hex 文件分为三部分(可通过 map 文件查看到)
    .text 代码段

  3. .data 数据段

  1. .bss, .stack, .heap的位置信息(即起始位置和大小)

程序运行时,这5段各起什么作用,又在物理存储空间哪个位置?
现在的计算机架构主要有两种:

  1. 冯诺依曼架构:必须从 RAM 中取出执行代码,即执行代码要先存入 RAM 中。
  2. 哈佛架构:可以直接从 flash 执行代码。
    ARM 架构是哈佛架构,可以直接从 flash 取指令执行,所以在程序运行期间:
    .text 段位于 flash 内,具体位置和 hex 文件中 .text 段的位置一致,程序运行时直接从 flash 内读取指令并执行。.text 段都是代码和常量,只读,所以可以放在 flash 内。
    .data 段在MCU启动过程中,会被从 flash 内 copy 到 SRAM 内(各家的启动代码都会做此操作)。程序运行时是操作 SRAM 中的变量。 .data 段内都是变量,可读可写,所以会被放在 SRAM 内。所以 .data 段有两个地址,一个是在 flash 内的地址,flash 内放的就是变量的初始值;另一个是在 SRAM 内的地址,SRAM 内的地址就是程序运行时变量所在的位置。一个变量初始化的过程,就是启动代码将 .data 段从 flash 内 copy 到 SRAM 中的过程,因此 SRAM 中的 .data 区域,在程序运行时(MCU 启动代码运行之后)一开始就有值了。这也解释了,为什么 static 变量的初始化只执行一次(即在编译时初始化),注意这种通过启动代码 copy flash 中内容到对应 SRAM 中的所谓在编译时初始化,和函数内部局部变量是通过用户代码初始化是不一样的操作,局部变量通过用户代码初始化后面会详细讲解。另外要注意,.data 段内数据分有初始值的全局变量和 static 变量两块,这两块变量虽然都在 .data 段,但作用域不同,全局变量是全局作用域,而 static 变量是局部作用域。
    .bss, .stack 和 .heap 段在 hex 文件内有对应的起始位置和大小信息,MCU 在启动时(启动代码)会根据这些信息配置 SRAM,给这三段在 SRAM 中按 hex 文件中的信息分配好对应的位置和大小。程序运行期间,对这三段的操作都是在 SRAM 中进行的。注意 .bss 要初始化,一般是启动代码会做这个操作,将整个 .bss 段初始化为 0 (可参考bss段为什么要初始化)。
    总结一下这5段在物理存储器上的位置及占用大小:
    Flash 占用大小 = .text 大小 + .data大小 + 其它section(如.bss, .stack, .heap等) 位置信息大小
    SRAM 占用大小 = .data 大小 + .bss 大小 + .stack大小 + .heap大小
    程序运行时,这 5 段在物理存储器上的位置如下图

下面用一段代码来详细介绍上面这5段

各变量所在位置如上图注释,下面把一些重点概念,如函数中的局部变量如何赋值,用此代码讲解一下:
在编译时初始化和函数内局部变量用户代码初始化
如下图

全局变量 a 和 静态变量 e 是在编译时初始化:这两个变量都在 .data 段,MCU 启动时,启动代码会将 .data 段从 flash copy 到 SRAM ,copy 操作完成后, SRAM .data 段中的变量就都已经有了初始值(之前存在 flash 中的初始值)。本例中的变量 a 和 c 就是在这个过程中完成的初始化。这个初始化过程中,不需要调用任何用户代码,所以被称作在编译时初始化。注意:编译时初始化只初始化一次。因为是启动代码执行 copy 操作完成的初始化,启动代码只执行一次,所以这个初始化的操作也就只会执行一次。
局部变量 g 在 .stack 中,也就是说,只有在程序运行时,并在调用 main 函数时,才会在 SRAM 的 stack 区域内给变量 g 开出一个空间,让程序可以对 g 进行操作。那如何对变量 g 赋初始值 2 的呢?是执行 g = 2; 这段代码,g =2; 这段代码在 .text 中(存在 flash 中),每次调用 fun 函数时都会调用 g = 2; 这段代码,这段代码会给在 stack 中的变量 g 赋初始值 2。但和编译时初始化不同,每次调用 fun 函数,都会重新对变量 g 做赋值操作,即函数被调用几次,函数内局部变量的初始化操作就会执行几次。所以用户代码初始化函数内局部变量会初始化多次。
函数内局部变量初始化和函数内静态变量初始化的区别

局部变量 g 的初始化上面已详细讲解。
局部静态变量 y 的初始化和 g 不同,静态变量 y 是在 .data 段中,和全局变量 a 一样,是用在编译时初始化的方法完成初始化的。详细过程参考上面关于变量 a 的初始化过程。
注意:这样 g 和 y 在初始化值方面的用法就完全不同了。在 fun 函数每次被调用时, g 都被初始化为2,而 y 则不是一直是 3,y 的值是上次 fun 被调用时 y 被赋的值(类似静态变量 y 使用的实例参考本链接)。
用 g 和 y 在 SRAM 中的位置也可以解释不同:g 处于 SRAM 的 stack 区域,只有 fun 函数被调用时才给 g 分配空间,并且每次分配后,都会对 g 赋初始值 2,所以每次调用 fun 函数,g 初始值都是2,并且函数 fun 执行完后下一句指令(pull)会自动注销 g 在 stack 中的空间;而 y 处于 SRAM 的 .data 区域,y 在 SRAM中有一个固定的物理空间,即使 fun 函数执行完毕,y 在 SRAM 中还是有一个空间保留着 y 的值,static int y = 3; 这句其实和定义全局变量初始值一样,只是在编译时将 y 放在了 .data段,并在 flash 中保存了其初始值 3, 这样在 MCU 启动时完成了对 y 的初始化,y 也就只在这时等于 3,之后 fun 执行中只要改变了 y 的值,下次再调用 fun 时,y 中还是上次的值,y=3; 这句代码完全不会执行。
static 变量详细介绍和使用可查看本链接。
对于常量

c 位置在 .text 段,程序运行期间 c 是在 flash 内,即程序要用到 c 时会去 flash 的 c 地址处直接取值。和全局变量 a 不同,启动代码不会 copy c 到 SRAM 中,SRAM 中不会有 c 的位置。
Code, RO, RW, ZI
这些只是用 keil 编译器时,对 .text, .data, .bss, .statck, .heap 这 5 段的不同称呼,详细介绍可参考本链接。简单总结如下:
Code:代码的大小
RO:常量所占空间
RW:程序中已经初始化的变量所占空间
ZI:未初始化的static和全局变量以及堆栈所占的空间
Flash占用大小=Code+RO+RW
SRAM占用大小=RW+ZI

参考链接:
https://blog.csdn.net/phenixyf/article/details/116718762
https://blog.csdn.net/lwbeyond/article/details/7275561#

堆栈,数据,文本,heap,bss,text data,stack相关推荐

  1. BSS段 data段 text段 堆heap 和 栈stack

    BSS段:BSS段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域.BSS是英文Block Started by Symbol的简称.BSS段属于静态内存分配.     ...

  2. Linux内存管理(.text .data .bss)

    Linux内存管理 orisun@orisun-desktop:~/Program$size memory2 text data bss dec hexfilename 2074 284 16 237 ...

  3. bss、data、rodata和text

    在ELF格式的可执行文件中,全局内存包括三种:bss.data和rodata.其它可执行文件格式与之类似.了解了这三种数据的特点,我们才能充分发挥它们的长处,达到速度与空间的最优化. 1.bss(Bl ...

  4. matlab之向数据点添加文本说明函数text

    目录 一.功能 二.语法 1.text(x,y,txt) 2.text(x,y,z,txt) 3.text(___,Name,Value) 4.text(ax,___) 5.t = text(___) ...

  5. 代码区,初始化全局数据区,BSS,堆区,栈区,程序环境变量区简介

    相关链接: 1.http://blog.csdn.net/wudebao5220150/article/details/12947445 2.http://www.360doc.com/content ...

  6. [转载] Python大数据文本分析及应用

    参考链接: 使用Python的SQL 3(处理大数据) 实践课题报告: 大数据文本分析与应用 学 校:xxx 学 院:大数据与智能工程学院 专 业:信息工程(数据科学与大数据技术) 年 级:2017级 ...

  7. 《Mining Text Data》阅读笔记---第1章 An Introduction to Text Mining

    这是一本关于文本挖掘的很厚的英文电子书,看英文大部头,很容易边看边忘记. 1.An Introduction to Text Mining 1.1 介绍 文本挖掘的三个问题: a. 主要的算法模型是什 ...

  8. Data Catalog3.0:Modern Metadata for the Modern Data Stack

    从2020年开始,在数据领域中,有一个比较流行的术语:The Modern Data Stack(现代数据堆栈),简单理解就是汇集了处理海量数据的最佳工具集.这包括在最好的工具上建立数据基础设施,如用 ...

  9. MySQL的文本导入之load data local

    MySQL的文本导入load data local 数据文件格式: Aeschylus time as he grows old teaches many lessons Alexander Grah ...

最新文章

  1. keepalived+nginx负载均衡+ApacheWeb实现高可用
  2. 814. Binary Tree Pruning
  3. 打造万能的Python开发环境
  4. HTTP,FTP,TCP,UDP及SOCKET
  5. C++ 大话数据结构 09: 中缀表达式 转后缀表达式 计算器
  6. linux lspci信息 详解_Linux引导之EFI SHELL详解
  7. (set)计算集合的并
  8. 【前端必备】七、页面性能优化
  9. P2424 约数和 真丶除法分块
  10. @configuration注解_SpringBoot注解大全,收藏一波!!!
  11. 暴风影音CEO冯鑫的人生解读
  12. R语言超星学习通习题
  13. 第二章 SPSS 的数据管理
  14. 最常用的编写Linux脚本命令和语法
  15. 210917-电脑护眼模式总结
  16. linux 公社资料
  17. neo4j :rel_Neo4j:足球转移图表
  18. 记事狗微博php,记事狗微博系统_366rtc
  19. 【Lintcode】1375. Substring With At Least K Distinct Characters
  20. 小程序app.js的配置

热门文章

  1. 浅显易懂 Makefile 入门 (08)— 默认 shell (/bin/sh)、命令回显、make参数(-n 只显示命令但不执行,-s 禁止所有回显)、单行命令、多行命令、并发执行
  2. Redis学习之路(一)--下载安装redis
  3. SpringCloud Alibaba微服务实战(五) - Sentinel实现限流熔断
  4. 写好 Python 代码的几条原则
  5. fastbert解读
  6. GPU上的快速光谱图分区
  7. x86 cpu卷积网络的自动调谐
  8. 适用于Windows和Linux的Yolo-v3和Yolo-v2(下)
  9. 2021年大数据Spark(三十三):SparkSQL分布式SQL引擎
  10. Python爬虫实战糗事百科实例