基於STM32分析棧、堆、全局區、常量區、代碼區、RAM、ROM(轉)

轉自:https://blog.csdn.net/lin_duo/article/details/103019390


總體介紹

在一個STM32程序代碼中,從內存高地址到內存低地址,依次分佈着棧區、堆區、全局區(靜態區)、常量去、代碼區,其中全局區中高地址分佈着.bss段,低地址分佈着.data段。總的分佈如下圖所示

內存高地址 棧區
堆區
.bss段
.data段
常量區
內存低地址 代碼區

下面分別對每一個區做詳細的介紹。

棧區(stack)

  • 臨時創建的局部變量存放在棧區。
  • 函數調用時,其入口參數存放在棧區。
  • 函數返回時,其返回值存放在棧區。
  • const定義的局部變量存放在棧區。

堆區(heap)

  • 堆區用於存放程序運行中被動態分佈的內存段,可增可減。
  • 可以有malloc等函數實現動態分佈內存。
  • 有malloc函數分佈的內存,必須用free進行內存釋放,否則會造成內存泄漏。

全局區(靜態區)

全局區有.bss段和.data段組成,可讀可寫。

.bss段

  • 未初始化的全局變量存放在.bss段。
  • 初始化爲0的全局變量和初始化爲0的靜態變量存放在.bss段。
  • .bss段不佔用可執行文件空間,其內容有操作系統初始化。

.data段

  • 已經初始化的全局變量存放在.data段。
  • 靜態變量存放在.data段。
  • .data段佔用可執行文件空間,其內容有程序初始化。
  • const定義的全局變量存放在.rodata段。

常量區

  • 字符串存放在常量區。
  • 常量區的內容不可以被修改。

代碼區

  • 程序執行代碼存放在代碼區。
  • 字符串常量也有可能存放在代碼區。

通過上面的介紹,可能你對各個數據的存儲位置還是很模糊,下面通過一個簡單的程序,再來體會理解一下。

#include <stdio.h>

static unsigned int val1 = 1; //val1存放在.data段

unsigned int val2 = 1; //初始化的全局變量存放在.data段

unsigned int val3 ; //未初始化的全局變量存放在.bss段

const unsigned int val4 = 1;  //val4存放在.rodata(只讀數據段)


unsigned char Demo(unsigned int num) // num 存放在棧區
{
	char var = "123456";    // var存放在棧區,"123456"存放在常量區
	
	unsigned int num1 = 1 ; // num1存放在棧區
	
	static unsigned int num2 = 0; // num2存放在.data段

    const unsigned int num3 = 7;  //num3存放在棧區

	void *p;
	
	p = malloc(8); //p存放在堆區
	
	free(p);

    return 1;
}

void main()
{
	unsigned int num = 0 ;
	num = Demo(num); //Demo()函數的返回值存放在棧區。
}

上面我們已經對堆、棧、全局區、常量區、代碼區進行了全面的分析,也舉例進行了說明。下面我們在對這些區存放在哪種介質上進行討論。

RAM和ROM、Flash Memory的物理特性

首先,我們需要明白RAM和ROM、Flash Memory的物理特性。

RAM

RAM又稱隨機存取存儲器,存儲的內容可通過指令隨機讀寫訪問。RAM中的存儲的數據在掉電是是會丟失,因而只能在開機運行時存儲數據。其中RAM又可以分爲兩種,一種是Dynamic RAM(DRAM動態隨機存儲器),另一種是Static RAM(SRAM,靜態隨機存儲器)。

ROM

ROM又稱只讀存儲器,只能從裏面讀出數據而不能任意寫入數據。ROM與RAM相比,具有價格高,容量小的缺點。但由於其具有掉電後數據可保持不變的優點,因此常用也存放一次性寫入的程序和數據,比如主版的BIOS程序的芯片就是ROM存儲器。

Flash Memory

由於ROM具有不易更改的特性,後面就發展了Flash Memory。Flash Memory不僅具有ROM掉電不丟失數據的特點,又可以在需要的時候對數據進行更改,不過價格比ROM要高。

不同數據的存放位置

由前面的分析我們知道,代碼區和常量區的內容是不允許被修改的,ROM(STM32就是Flash Memory)也是不允許被修改的,所以代碼區和常量區的內容編譯後存儲在ROM中。

而棧、堆、全局區(.bss段、.data段)都是存放在RAM中。

至此,關於不同數據存放哪個區域已經全部介紹完了。下面還將介紹一下Keil 的Build Output窗口。

Keil 的Build Output窗口

如上圖,存在Code、RO-data、RW-data、ZI-data四個代碼段大小。

其中Code就是代碼佔用大小,RO-data是隻讀常量、RW-data是已初始化的可讀可寫變量,ZI-data是未初始化的可讀可寫變量。

有些時候,我們需要知道RAM和ROM的使用情況如何,那麼我們就可以使用下面的公式計算。

RAM = RW-data + ZI-data

ROM = Code + RO-data + RW-data

發佈了7 篇原創文章 · 獲贊 9 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章