变量存储重温、CLion编辑器的学习与实践
文章目录
1 内存分配问题
1.1 全局变量、局部变量、堆、栈等概念
在STM32中,内存分布总体情况如下表:
内存高地址 | 栈区 |
---|---|
内存高地址 | 堆区 |
内存高地址 | .bss段 |
内存高地址 | .data段 |
内存高地址 | 常量区 |
内存低地址 | 代码区 |
-
栈区(stack)
存放局部变量,函数入口参数以及返回值。
由于栈的先进先出(FIFO)特点,它支持两个操作,PUSH和POP。PUSH是将数据放到栈的顶端,POP是将栈顶的数据取出。动态数据存放在堆栈中。所以栈特别方便用来保存/恢复调用现场;我们可以把堆栈看成一个寄存、交换临时数据的内存区。
-
堆区(heap)
存放程序运行中被动态分配的内存段,全局变量。
可以用
malloc
等函数实现动态内存分布,且必须使用free
进行内存释放,否则会导致内存泄漏。 -
全局区(静态区static)
.bss段
存放未初始化的全局变量、初始化为零的全局变量、初始化为零的静态变量。
不占用可执行文件空间,其内容由操作系统初始化。属于静态内存分配。
.data段
存放已经初始化的全局变量、静态变量。(const定义的全局变量存放在.rodata段)
占用可执行文件空间,其内容由程序初始化。属于动态内存分配。
-
常量区
存放字符串。
常量区的内容不可以被修改。
-
代码区(text)
存放程序执行代码,字符串常量也有可能存放在代码区。
这部分区域的大小在程序运行前就已经确定。
一个程序本质上都是由 bss 段、data 段、text 段三个组成。一般在初始化时 bss 段部分将会清零,bss 段属于静态内存分配,即程序一开始就将其清零了。
比如,在C语言之类的程序编译完成之后,已初始化的全局变量保存在.data 段中,未初始化的全局变量保存在.bss 段中。
text和data段都在可执行文件中(在嵌入式系统里一般是固化在镜像文件中),由系统从可执行文件中加载,而bss段不在可执行文件中,由系统初始化。
1.2 STM32数据的存储位置
ROM (Read Only Memory)程序存储器
-
ROM全称Read Only Memory,顾名思义,它是一种只能读出事先所存的数据的固态半导体存储器。ROM中所存数据稳定,一旦存储数据就再也无法将之改变或者删除,断电后所存数据也不会消失。其结构简单,因而常用于存储各种固化程序和数据。
-
在单片机中用来存储程序数据及常量数据或变量数据,凡是c文件及h文件中所有代码、全局变量、局部变量、‘const’限定符定义的常量数据、startup.asm文件中的代码(类似ARM中的bootloader或者X86中的BIOS,一些低端的单片机是没有这个的)通通都存储在ROM中。
RAM (Random Access Memory)随机访问存储器
-
RAM又称随机存取存储器,存储单元的内容可按照需要随机取出或存入,且存取的速度与存储单元的位置无关。这种存储器在断电时,将丢失其存储内容,所以主要用于存储短时间使用的程序。
-
它主要用来存储程序中用到的变量。凡是整个程序中,所用到的需要被改写的量(包括全局变量、局部变量、堆栈段等),都存储在RAM中。
FLASH 存储器
- Flash 存储器(FLASH EEPROM)又称闪存,快闪。它是EEPROM的一种。它结合了ROM和RAM的长处。不仅具备电子可擦除可编辑(EEPROM)的性能,还不会断电丢失数据同时可以快速读取数据。
- 它于EEPROM的最大区别是,FLASH按扇区(block)操作,而EEPROM按照字节操作。FLASH的电路结构较简单,同样容量占芯片面积较小,成本自然比EEPROM低,因此适合用于做程序存储器。
ROM、RAM、Flash的区别
- 在应用中,常规上ROM是用来存储固化程序的,RAM是用来存放数据的。由于FLASH ROM比普通的ROM读写速度快,擦写方便,一般用来存储用户程序和需要永久保存的数据。
- 代码区和常量区的内容是不允许被修改的,ROM(STM32就是Flash Memory)也是不允许被修改的,所以代码区和常量区的内容编译后存储在ROM中。而栈、堆、全局区(.bss段、.data段)都是存放在RAM中。
Keil中,如下图:ROM从0x8000000开始,大小是0x10000;RAM从0x20000000开始,大小是0x5000 。
2 基于Ubuntu的变量地址分配的验证
2.1 实现过程
Ubuntu下打开终端,键入命令:
gedit //编写程序并保存
代码如下:
#include <stdio.h>
#include <stdlib.h>
//定义全局变量
int init_global_a = 1;
int uninit_global_a;
static int inits_global_b = 2;
static int uninits_global_b;
void output(int a)
{
printf("hello world!");
printf("%d",a);
printf("\n");
}
int main( )
{
//定义局部变量
int a=2;//栈
static int inits_local_c=2, uninits_local_c;
int init_local_d = 1;//栈
output(a);
char *p;//栈
char str[10] = "zh";//栈
//定义常量字符串
char *var1 = "1234567890";
char *var2 = "abcdefghij";
//动态分配——堆区
int *p1=malloc(4);
int *p2