亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C程序中Ubuntu、stm32的內(nèi)存分配問(wèn)題

 更新時(shí)間:2021年12月23日 16:03:09   作者:Lc-Yusheng  
這篇文章主要介紹了C程序中Ubuntu、stm32的內(nèi)存分配問(wèn)題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

一、內(nèi)存分區(qū)概念介紹

1.1、C/C++編譯程序的內(nèi)存占用

1、棧區(qū)(stack)
由編譯器自動(dòng)分配釋放,存放函數(shù)的參數(shù)值,局部變量的值等。其操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧。
2、堆區(qū)(heap)
一般由程序員分配釋放,若程序員不釋放,程序結(jié)束時(shí)可能由OS回收 。它與數(shù)據(jù)結(jié)構(gòu)中的堆不同,分配方式類似于鏈表。
3、全局區(qū)(靜態(tài)區(qū))(static)
全局變量和靜態(tài)變量的存儲(chǔ)是放在一塊的,初始化的全局變量和靜態(tài)變量在一塊區(qū)域, 未初始化的全局變量、未初始化的靜態(tài)變量在相鄰的另一塊區(qū)域。當(dāng)程序結(jié)束后,變量由系統(tǒng)釋放 。
4、文字常量區(qū)
存放常量字符串。當(dāng)程序結(jié)束后,常量字符串由系統(tǒng)釋放 。
5、程序代碼區(qū)
存放函數(shù)體的二進(jìn)制代碼。

1、從靜態(tài)存儲(chǔ)區(qū)域分配。內(nèi)存在程序編譯的時(shí)候就已經(jīng)分配好,這塊內(nèi)存在程序的整個(gè)運(yùn)行期間都存在。例如全局變量,static變量。

2、在棧上創(chuàng)建。在執(zhí)行函數(shù)時(shí),函數(shù)內(nèi)局部變量的存儲(chǔ)單元都可以在棧上創(chuàng)建,函數(shù)執(zhí)行結(jié)束時(shí)這些存儲(chǔ)單元自動(dòng)被釋放。棧內(nèi)存分配運(yùn)算內(nèi)置于處理器的指令集中,效率很高,但是分配的內(nèi)存容量有限。
3、從堆上分配,亦稱動(dòng)態(tài)內(nèi)存分配。程序在運(yùn)行的時(shí)候用malloc或new申請(qǐng)任意多少的內(nèi)存,程序員自己負(fù)責(zé)在何時(shí)用free或delete釋放內(nèi)存。動(dòng)態(tài)內(nèi)存的生存期由程序員決定,使用非常靈活,但如果在堆上分配了空間,就有責(zé)任回收它,否則運(yùn)行的程序會(huì)出現(xiàn)內(nèi)存泄漏,頻繁地分配和釋放不同大小的堆空間將會(huì)產(chǎn)生堆內(nèi)碎塊。

1.2、棧和堆、全局/靜態(tài)存儲(chǔ)區(qū)和常量存儲(chǔ)區(qū)的對(duì)比

1、棧區(qū): 主要用來(lái)存放局部變量, 傳遞參數(shù), 存放函數(shù)的返回地址。.esp 始終指向棧頂, 棧中的數(shù)據(jù)越多, esp的值越小。

2、堆區(qū): 用于存放動(dòng)態(tài)分配的對(duì)象, 當(dāng)你使用 malloc和new 等進(jìn)行分配時(shí),所得到的空間就在堆中。動(dòng)態(tài)分配得到的內(nèi)存區(qū)域附帶有分配信息, 所以你能夠 free和delete它們。

3、數(shù)據(jù)區(qū): 全局,靜態(tài)和常量是分配在數(shù)據(jù)區(qū)中的,數(shù)據(jù)區(qū)包括bss(未初始化數(shù)據(jù)區(qū))和初始化數(shù)據(jù)區(qū)。 ?

注意: 堆向高內(nèi)存地址生長(zhǎng); 棧向低內(nèi)存地址生長(zhǎng); 堆和棧相向而生,堆和棧之間有個(gè)臨界點(diǎn),稱為stkbrk。

1.3、圖片說(shuō)明

?

補(bǔ)充:

Stack: 棧,存放Automatic Variables,按內(nèi)存地址由高到低方向生長(zhǎng),其最大大小由編譯時(shí)確定,速度快,但自由性差,最大空間不大。
Heap: 堆,自由申請(qǐng)的空間,按內(nèi)存地址由低到高方向生長(zhǎng),其大小由系統(tǒng)內(nèi)存/虛擬內(nèi)存上限決定,速度較慢,但自由性大,可用空間大。
每個(gè)線程都會(huì)有自己的棧,但是堆空間是共用的。

參考文獻(xiàn):https://www.icode9.com/content-1-772915.html?

?二、C語(yǔ)言編程論證

1.1、Ubuntu測(cè)試代碼實(shí)現(xiàn)

1、main.c:

#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");
	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] = "lyy";
    //定義常量字符串
    char *var1 = "1234567890";
    char *var2 = "qwertyuiop";
    //動(dòng)態(tài)分配
    int *p1=malloc(4);
    int *p2=malloc(4);
    //釋放
    free(p1);
    free(p2);
    printf("棧區(qū)-變量地址\n");
    printf("                a:%p\n", &a);
    printf("                init_local_d:%p\n", &init_local_d);
    printf("                p:%p\n", &p);
    printf("              str:%p\n", str);
    printf("\n堆區(qū)-動(dòng)態(tài)申請(qǐng)地址\n");
    printf("                   %p\n", p1);
    printf("                   %p\n", p2);
    printf("\n全局區(qū)-全局變量和靜態(tài)變量\n");
    printf("\n.bss段\n");
    printf("全局外部無(wú)初值 uninit_global_a:%p\n", &uninit_global_a);
    printf("靜態(tài)外部無(wú)初值 uninits_global_b:%p\n", &uninits_global_b);
    printf("靜態(tài)內(nèi)部無(wú)初值 uninits_local_c:%p\n", &uninits_local_c);
    printf("\n.data段\n");
    printf("全局外部有初值 init_global_a:%p\n", &init_global_a);
    printf("靜態(tài)外部有初值 inits_global_b:%p\n", &inits_global_b);
    printf("靜態(tài)內(nèi)部有初值 inits_local_c:%p\n", &inits_local_c);
    printf("\n文字常量區(qū)\n");
    printf("文字常量地址     :%p\n",var1);
    printf("文字常量地址     :%p\n",var2);
    printf("\n代碼區(qū)\n");
    printf("程序區(qū)地址       :%p\n",&main);
    printf("函數(shù)地址         :%p\n",&output);
    return 0;
}

2、使用命令創(chuàng)建一個(gè) main.c 文件:

gedit main.c

3、復(fù)制粘貼上述代碼

4、編譯執(zhí)行

gcc main.c -o main

./main

5、結(jié)果展示

?

分析說(shuō)明:可以從上圖可以得出棧區(qū)內(nèi)存地址由高到低方向生長(zhǎng),堆區(qū)內(nèi)存地址由低到高方向生長(zhǎng)。而且整個(gè)程序的內(nèi)存也是從高到低的地址進(jìn)行分配的。?

?1.2、STM32驗(yàn)證代碼實(shí)現(xiàn)

打開(kāi)之前做過(guò)的串口通訊實(shí)驗(yàn)代碼,在其中進(jìn)行修改,后面我也會(huì)給出先關(guān)串口鏈接

1、代碼更改

修改bsp_usart.h :

添加頭文件:

#include <stdio.h>
#include <stdlib.h>

?修改bsp_usart.c :

重寫(xiě) fputc 函數(shù):

int fputc(int ch, FILE *f)
{
	USART_SendData(DEBUG_USARTx, (uint8_t)ch);
	
	while(USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET);
	
	return (ch);
}

main.c?:?

#include "stm32f10x.h"
#include "bsp_usart.h"  //添加 bsp_usart.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");
	printf("%d",a);
	printf("\n");
}
 
int main(void)
{	
	//定義局部變量
	int a=2;
	static int inits_local_c=2, uninits_local_c;
	int init_local_d = 1;
	char *p;
	char str[10] = "lyy";
	//定義常量字符串
	char *var1 = "1234567890";
	char *var2 = "qwertyuiop";
	//動(dòng)態(tài)分配
	int *p1=malloc(4);
	int *p2=malloc(4);
	USART_Config();//串口初始化
	output(a);
	//釋放
	free(p1);
	free(p2);
	printf("棧區(qū)-變量地址\n");
	printf("                a:%p\n", &a);
	printf("                init_local_d:%p\n", &init_local_d);
	printf("                p:%p\n", &p);
	printf("              str:%p\n", str);
	printf("\n堆區(qū)-動(dòng)態(tài)申請(qǐng)地址\n");
	printf("                   %p\n", p1);
	printf("                   %p\n", p2);
	printf("\n全局區(qū)-全局變量和靜態(tài)變量\n");
	printf("\n.bss段\n");
	printf("全局外部無(wú)初值 uninit_global_a:%p\n", &uninit_global_a);
	printf("靜態(tài)外部無(wú)初值 uninits_global_b:%p\n", &uninits_global_b);
	printf("靜態(tài)內(nèi)部無(wú)初值 uninits_local_c:%p\n", &uninits_local_c);
	printf("\n.data段\n");
	printf("全局外部有初值 init_global_a:%p\n", &init_global_a);
	printf("靜態(tài)外部有初值 inits_global_b:%p\n", &inits_global_b);
	printf("靜態(tài)內(nèi)部有初值 inits_local_c:%p\n", &inits_local_c);
	printf("\n文字常量區(qū)\n");
	printf("文字常量地址     :%p\n",var1);
	printf("文字常量地址     :%p\n",var2);
	printf("\n代碼區(qū)\n");
	printf("程序區(qū)地址       :%p\n",&main);
	printf("函數(shù)地址         :%p\n",&output);
	return 0;
}

2、編譯輸出

3、燒錄

打開(kāi)串口調(diào)試助手,打開(kāi)串口后,按一下 RESET 鍵,顯示結(jié)果:

?4、分析說(shuō)明

? ?與Ubuntu一樣,stm32的棧區(qū)的地址值是從上到下減小的,堆區(qū)則是從上到下增長(zhǎng)的。從每個(gè)區(qū)來(lái)看,地址值是從上到下逐步減小的,即棧區(qū)的地址是高地址,代碼區(qū)的地址是處于低地址。

1.3、keil下stm32存儲(chǔ)觀察

stm32數(shù)據(jù)的存儲(chǔ)位置

1、RAM(隨機(jī)存取存儲(chǔ)器)
存儲(chǔ)的內(nèi)容可通過(guò)指令隨機(jī)讀寫(xiě)訪問(wèn)。RAM中的存儲(chǔ)的數(shù)據(jù)在掉電是會(huì)丟失,因而只能在開(kāi)機(jī)運(yùn)行時(shí)存儲(chǔ)數(shù)據(jù)。其中RAM又可以分為兩種,一種是Dynamic RAM(DRAM動(dòng)態(tài)隨機(jī)存儲(chǔ)器),另一種是Static RAM(SRAM,靜態(tài)隨機(jī)存儲(chǔ)器)。棧、堆、全局區(qū)(.bss段、.data段)都是存放在RAM中。
2、ROM(只讀存儲(chǔ)器)
只能從里面讀出數(shù)據(jù)而不能任意寫(xiě)入數(shù)據(jù)。ROM與RAM相比,具有讀寫(xiě)速度慢的缺點(diǎn)。但由于其具有掉電后數(shù)據(jù)可保持不變的優(yōu)點(diǎn),因此常用也存放一次性寫(xiě)入的程序和數(shù)據(jù),比如主版的BIOS程序的芯片就是ROM存儲(chǔ)器。代碼區(qū)和常量區(qū)的內(nèi)容是不允許被修改的,所以存放于ROM中。

查看:

分析說(shuō)明:

? ? 從圖片中可以看出ROM的地址分配是從0x8000000開(kāi)始,整個(gè)大小為0x40000,這個(gè)部分用于存放代碼區(qū)和文字常量區(qū)。RAM的地址分配是從0x20000000開(kāi)始,其大小是0xC000,這個(gè)區(qū)域用來(lái)存放棧、堆、全局區(qū)(.bss段、.data段)。與代碼結(jié)果顯示進(jìn)行對(duì)比,也可以看出對(duì)應(yīng)得部分得地址與設(shè)置的是相對(duì)應(yīng)的。?

三、總結(jié)

? ?通過(guò)對(duì)C語(yǔ)言程序里全局變量、局部變量、堆、棧等概念的重溫以及在不同平臺(tái)進(jìn)行編程驗(yàn)證,熟悉掌握了C語(yǔ)言中相關(guān)概念,并對(duì)整體的內(nèi)存地址分配由高到低,以及棧區(qū)內(nèi)存地址由高到低方向生長(zhǎng),堆區(qū)內(nèi)存地址由低到高方向生長(zhǎng)進(jìn)行了驗(yàn)證。經(jīng)過(guò)本次實(shí)驗(yàn),主要是對(duì)C程序的內(nèi)存分配有進(jìn)一步的認(rèn)識(shí),知道一個(gè)C程序內(nèi)存應(yīng)該包括哪些部分。其中,主要是程序段、數(shù)據(jù)段、堆棧三個(gè)部分。不同系統(tǒng)下面,區(qū)域內(nèi)的地址值變化是不相同。總的來(lái)說(shuō),是對(duì)內(nèi)存的分配有了比較新的認(rèn)識(shí)。

四、參考資料

https://blog.csdn.net/qq_43279579/article/details/110308101

https://blog.csdn.net/ssj925319/article/details/110727925?spm=1001.2014.3001.5501?

USART串口通信:

鏈接: https://pan.baidu.com/s/1YspOK2I3Ddm5XntKXKRnXA

提取碼: emev?

到此這篇關(guān)于C程序中Ubuntu、stm32的內(nèi)存分配問(wèn)題的文章就介紹到這了,更多相關(guān)C程序Ubuntu、stm32的內(nèi)存分配內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 深入C++中struct與class的區(qū)別分析

    深入C++中struct與class的區(qū)別分析

    本篇文章是對(duì)C++中struct與class的區(qū)別進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • c++先序二叉樹(shù)的構(gòu)建詳解

    c++先序二叉樹(shù)的構(gòu)建詳解

    在本篇文章里小編給大家分享了關(guān)于c++先序二叉樹(shù)的構(gòu)建的相關(guān)知識(shí)點(diǎn),需要的朋友們跟著學(xué)習(xí)下。
    2019-04-04
  • C語(yǔ)言實(shí)現(xiàn)電腦關(guān)機(jī)程序

    C語(yǔ)言實(shí)現(xiàn)電腦關(guān)機(jī)程序

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)電腦關(guān)機(jī)程序,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-02-02
  • C++之Qt5雙緩沖機(jī)制案例教程

    C++之Qt5雙緩沖機(jī)制案例教程

    這篇文章主要介紹了C++之Qt5雙緩沖機(jī)制案例教程,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • C++無(wú)法重載點(diǎn)符號(hào)、::、sizeof等的原因

    C++無(wú)法重載點(diǎn)符號(hào)、::、sizeof等的原因

    這篇文章主要介紹了C++無(wú)法重載點(diǎn)符號(hào)、::、sizeof等的原因的相關(guān)資料,需要的朋友可以參考下
    2016-05-05
  • 老程序員教你一天時(shí)間完成C語(yǔ)言掃雷游戲

    老程序員教你一天時(shí)間完成C語(yǔ)言掃雷游戲

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)掃雷游戲初級(jí)版,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • OpenCV實(shí)現(xiàn)馬賽克功能

    OpenCV實(shí)現(xiàn)馬賽克功能

    這篇文章主要為大家詳細(xì)介紹了OpenCV實(shí)現(xiàn)馬賽克功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • C++11中的chrono庫(kù)詳解

    C++11中的chrono庫(kù)詳解

    C++11提供了日期時(shí)間相關(guān)的庫(kù)chrono,通過(guò)chrono庫(kù)可以很方便的處理日期和時(shí)間,這篇文章主要介紹了C++11中的chrono庫(kù),需要的朋友可以參考下
    2023-03-03
  • C++設(shè)計(jì)模式之抽象工廠模式

    C++設(shè)計(jì)模式之抽象工廠模式

    這篇文章主要介紹了C++設(shè)計(jì)模式之抽象工廠模式,本文要講的抽象工廠模式,就是工廠方法模式的擴(kuò)展和延伸,需要的朋友可以參考下
    2014-09-09
  • C語(yǔ)言進(jìn)度條的實(shí)現(xiàn)原理詳解

    C語(yǔ)言進(jìn)度條的實(shí)現(xiàn)原理詳解

    這篇文章主要介紹了C語(yǔ)言進(jìn)度條的實(shí)現(xiàn)原理,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08

最新評(píng)論