91欧美超碰AV自拍|国产成年人性爱视频免费看|亚洲 日韩 欧美一厂二区入|人人看人人爽人人操aV|丝袜美腿视频一区二区在线看|人人操人人爽人人爱|婷婷五月天超碰|97色色欧美亚州A√|另类A√无码精品一级av|欧美特级日韩特级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

什么是堆內(nèi)存?堆內(nèi)存是如何分配的?

電子工程師 ? 來源:單片機匠人 ? 作者:蔡琰老師 ? 2021-07-05 17:58 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

上一篇我們分享了棧內(nèi)存的概念,現(xiàn)在我們分享下堆內(nèi)存的概念。

在一般的編譯系統(tǒng)中,堆內(nèi)存的分配方向和棧內(nèi)存是相反的。當棧內(nèi)存從高地址向低地址增長的時候,堆內(nèi)存從低地址向高地址分配。

C語言中,堆內(nèi)存在分配和釋放的時候,是程序通過調(diào)用C語言的庫函數(shù)完成的。這和棧內(nèi)存的分配有區(qū)別,棧內(nèi)存利用的是處理器的硬件機制,而堆內(nèi)存的處理使用的是庫函數(shù)。

我們來看下堆內(nèi)存的分配情況:

在堆內(nèi)存的分配過程中,每次分配將返回一個當前分配地址的指針。在程序中如果多次分配內(nèi)存,可以得到多個內(nèi)存指針,每個內(nèi)存指針都是本次分配內(nèi)存的地址。在釋放內(nèi)存的時候,只需要對每個指針進行操作,那個指針所指向的內(nèi)存就會被釋放,而對其他的內(nèi)存區(qū)域沒有影響。

從內(nèi)存的分配和使用上,可以看出棧內(nèi)存和堆內(nèi)存的區(qū)別:棧內(nèi)存只有一個入口點,就是棧指針,棧內(nèi)存壓入和彈出的時候棧指針將發(fā)生變化,棧指針標識當前棧區(qū)域中已使用和未使用的界限,程序在訪問棧內(nèi)存的時候都只能通過棧指針及其偏移量;而堆內(nèi)存有多個入口點,每次分配得到的指針是訪問內(nèi)存的入口,每個分配內(nèi)存區(qū)域都可以被單獨釋放,程序?qū)Χ褍?nèi)存可以通過每次分配得到的指針訪問。

堆內(nèi)存有一個整體分配的過程,按照向上的堆內(nèi)存分配方向。隨著堆內(nèi)存使用量的增加,堆內(nèi)存將逐漸向高地址分配。這只是一個大體的增長的方面,在堆內(nèi)存中,已使用的區(qū)域和未使用的區(qū)域是交錯的,而不是像棧區(qū)域那樣有明顯的分界線。

堆內(nèi)存的釋放看下面這個圖:

看到這樣頻繁的使用區(qū)域和釋放,那么很容易看出堆內(nèi)存是不連續(xù)的,跟堆內(nèi)存的使用方式有關(guān)系,這個分配就相對自由靈活了,但是也是會在低地址向高地址發(fā)展的方向分配的。

比如上面釋放后再分配就可以是下面兩種情況:

先看再次分配1的情況:當新分配的需求比中間(剛剛釋放)區(qū)域小,那么就會在緊接著的區(qū)域給分配。

再看再次分配2的情況:當新分配的需求比中間(釋放的)區(qū)域大,那么只能往后尋求能給的區(qū)域。

當頻繁的分配和釋放內(nèi)存的過程中,會很容易出現(xiàn)在兩塊已經(jīng)分配的內(nèi)存之間較小的未分配內(nèi)存區(qū)域,這些其實可以用,但是由于他們的空間比較小,不夠連續(xù)內(nèi)存的分配,所以分配的時候就很難再次使用,這些較小的內(nèi)存就是我們常說的內(nèi)存碎片。

我們再來聊一下在C程序中堆空間的使用。

在C語言中,堆內(nèi)存區(qū)域的分配和釋放是通過調(diào)用庫函數(shù)來完成的,實現(xiàn)的函數(shù)主要有四個:

void *malloc(size_t size); //分配內(nèi)存空間

void free(void *ptr); //釋放內(nèi)存空間

void *calloc(size_t nmemb,size_t size); //分配內(nèi)存空間

void *realloc(void * ptr,size_t size); //重新分配內(nèi)存空間

注意:使用上面這幾個函數(shù)需要包含標準庫文件

那么庫函數(shù)怎么使用呢,內(nèi)存分配了就要有釋放,那么常用的就是malloc()和free()兩個函數(shù)。malloc()函數(shù)的輸入是需要分配內(nèi)存的大小,輸出是分配內(nèi)存的指針。如果分配不成功,則返回NULL。

free()函數(shù)的輸入是需要釋放的指針,可以接受任何形式的指針。這個指針必須是由分配函數(shù)分配出來的。

例如:

int *pa;

pa = (int *)malloc(sizeof(int));//分配一個int大小的指針

if(NULL != pa)

{

free(pa);

}

內(nèi)存使用完成需要釋放,以便分配給其他程序使用。

calloc()也是內(nèi)存分配的,只是可以把分配好的內(nèi)存區(qū)域的初始值全部設(shè)置為0。還有這個分配內(nèi)存有兩個參數(shù),第一個是分配單元的大小,第二個是要分配的數(shù)目。

malloc(sizeof(unsigned int)*10); == calloc(sizeof(unsigned int),10)

realloc()有兩個參數(shù),一個是指向內(nèi)存的地址指針,一個是要重分配內(nèi)存的大小,返回值是指向所分配內(nèi)存的指針。

1、當參數(shù)指針為NULL的時候,作為malloc使用,分配內(nèi)存。

2、當重分配內(nèi)存大小為0的時候,作為free使用,釋放內(nèi)存。

3、當指針和重分配內(nèi)存大小均不為0的時候,根據(jù)指針指向的堆內(nèi)存區(qū)域的情況和指針大小重新分配內(nèi)存。

對于realloc()作為重新分配內(nèi)存的時候,有三種可能出現(xiàn):

1、縮小內(nèi)存

2、擴大內(nèi)存,不需要移動指針

3、擴大內(nèi)存,需要移動指針(指定內(nèi)存區(qū)域大小不夠)

在堆內(nèi)存的管理上,主要容易出現(xiàn)以下幾個問題:

1、開辟的內(nèi)存沒有釋放,造成內(nèi)存泄漏(系統(tǒng)不會釋放任何用戶分配的內(nèi)存)

2、野指針被使用或釋放(內(nèi)存釋放后,需要將內(nèi)存指針置為NULL)

3、非法釋放指針(分配了有效內(nèi)存才存在釋放,否則是非法的)

在C語言語法的方面對棧內(nèi)存和堆內(nèi)存如何使用沒有限制。然后從使用的角度,棧內(nèi)存更適用于容量較小的單個變量(例如:C語言的基本變量類型、較小的結(jié)構(gòu)體和數(shù)組),堆內(nèi)存則適用于開辟較大塊的內(nèi)存。棧內(nèi)存由編譯器分配和釋放,堆內(nèi)存由程序員分配和釋放。

責(zé)任編輯:lq6

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 內(nèi)存
    +關(guān)注

    關(guān)注

    9

    文章

    3209

    瀏覽量

    76357
  • C語言
    +關(guān)注

    關(guān)注

    183

    文章

    7644

    瀏覽量

    145565

原文標題:堆內(nèi)存的那些事

文章出處:【微信號:gh_e7f294a514ca,微信公眾號:單片機匠人】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點推薦

    curl中的TFTP實現(xiàn):整數(shù)下溢導(dǎo)致內(nèi)存越界讀取漏洞

    可能已經(jīng)超過了已分配的緩沖區(qū)大小。緊接著的第12行 sendto 調(diào)用就可能發(fā)送超出緩沖區(qū)邊界的數(shù)據(jù)。 1 2 3 4 5 6 7 8 9 10 影響 此漏洞的潛在影響是信息泄露,即可能將內(nèi)存中的內(nèi)容
    發(fā)表于 02-19 13:55

    keil中c語言的動態(tài)分配內(nèi)存

    于處理器的指令集中,效率很高,但是分配內(nèi)存容量有限。另外,當函數(shù)運行結(jié)束時,棧區(qū)的空間會被自動釋放。 (3)內(nèi)存映射段。該部分內(nèi)存主要用于文件映射、動態(tài)庫以及匿名映射。 (4)
    發(fā)表于 01-21 06:04

    【「Linux 設(shè)備驅(qū)動開發(fā)(第 2 版)」閱讀體驗】+讀深入理解Linux內(nèi)核內(nèi)存分配

    每個內(nèi)存地址是虛擬的,不是直接指向RAM中的任何地址。當用戶訪問內(nèi)存中的存儲單元時,都會進行地址轉(zhuǎn)換以匹配相應(yīng)的物理內(nèi)存。書籍的第10章討論了五個主題,對Linux內(nèi)核內(nèi)存
    發(fā)表于 01-16 20:05

    嵌入式系統(tǒng)中,動態(tài)分配內(nèi)存可能發(fā)生的問題是什么?

    盡管不像非嵌入式計算機那么常見,嵌入式系統(tǒng)還是有從(heap)中動態(tài)分配內(nèi)存的過程的。 那么嵌入式系統(tǒng)中,動態(tài)分配內(nèi)存可能發(fā)生的問題是什
    發(fā)表于 12-22 09:42

    三種類型內(nèi)存的使用

    給上級調(diào)用函數(shù)。通常被稱為“”。 靜態(tài)存儲:在程序的整個生命周期內(nèi)有效。在進程啟動時分配,全局變量都存儲在這里。 如果想通過一個函數(shù)“返回”內(nèi)存,不必通過調(diào)用 malloc,可以直接將一個指向
    發(fā)表于 12-12 06:43

    使用Keil MicroLIB時自動設(shè)置大小

    項目的過程中,市場遇到各種各樣問題,棧穿透到里面,或者不夠大,相當煩人! 有時候就在想,何不讓全局變量以外的所有RAM給堆棧共用? 因為從低到高分配,而棧從高到低
    發(fā)表于 12-09 07:04

    和棧的區(qū)別

    一個由C/C 編譯的程序占用的內(nèi)存分為以下幾個部分: 棧區(qū)(stack):由編譯器自動分配釋放 ,存放函數(shù)的參數(shù)值,局部變量的值等。其操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧。 區(qū)(heap):一般由
    的頭像 發(fā)表于 11-27 18:13 ?1078次閱讀

    如何在應(yīng)用程序調(diào)試期間分析棧和使用情況

    隨著 AMD Vitis 統(tǒng)一軟件平臺 2021.2 的發(fā)布,Vitis 引入了一個 Tcl 腳本,用于在應(yīng)用程序運行的特定時間點協(xié)助查找棧和內(nèi)存使用情況。該腳本已延續(xù)到后續(xù)的 Vitis 版本
    的頭像 發(fā)表于 10-24 16:54 ?888次閱讀
    如何在應(yīng)用程序調(diào)試期間分析棧和<b class='flag-5'>堆</b>使用情況

    WebGL/Canvas 內(nèi)存泄露分析

    的 JavaScript 對象未釋放要復(fù)雜得多。一個現(xiàn)代 WebGL/Canvas 應(yīng)用的內(nèi)存版圖實際上跨越了三個截然不同但又相互關(guān)聯(lián)的內(nèi)存區(qū)域: 圖 V8 引擎管理的 JavaScript (JS Heap
    的頭像 發(fā)表于 10-21 11:40 ?407次閱讀
    WebGL/Canvas <b class='flag-5'>內(nèi)存</b>泄露分析

    如何使用LAX_CODEGEN啟用動態(tài)內(nèi)存分配

    我目前正在探索NXP_MBDToolbox_LAX。lax_codegen 生成的代碼基于靜態(tài)分配。我想管理大型向量,如何使用 LAX_CODEGEN 啟用動態(tài)內(nèi)存分配
    發(fā)表于 04-10 08:09

    如何查看S32DS中S32平臺的內(nèi)存分配?

    大家好,我正在使用 s32DS for s32 平臺,我想查看我的項目的內(nèi)存分配。我想知道分配給對象的內(nèi)存以及它們被分配到哪里,例如 SRA
    發(fā)表于 04-09 07:30

    :整流電路的“中流砥柱”

    大家好!今天我們來聊一聊電子電路中一個非常重要的元器件——橋。無論是家用電器、工業(yè)設(shè)備,還是通信設(shè)備,橋都扮演著不可或缺的角色。它雖然看起來不起眼,但卻是整流電路的“中流砥柱”。那么,橋到底是
    的頭像 發(fā)表于 04-01 17:07 ?2712次閱讀

    golang內(nèi)存分配

    作者:錢文 Go 的分配采用了類似 tcmalloc 的結(jié)構(gòu).特點: 使用一小塊一小塊的連續(xù)內(nèi)存頁, 進行分配某個范圍大小的內(nèi)存需求. 比如某個連續(xù) 8KB 專門用于
    的頭像 發(fā)表于 03-31 15:00 ?514次閱讀
    golang<b class='flag-5'>內(nèi)存</b><b class='flag-5'>分配</b>

    快速搞懂C語言程序內(nèi)存分區(qū)!

    到動態(tài)分配的數(shù)據(jù)等內(nèi)容。(內(nèi)存分區(qū)圖示)理解這些內(nèi)存分區(qū)的結(jié)構(gòu)和特性,不僅有助于編寫更高效的代碼,還能幫助排查和解決如段錯誤、內(nèi)存泄漏、棧溢出等常見問題。以下是常見的六
    的頭像 發(fā)表于 03-14 17:37 ?1565次閱讀
    快速搞懂C語言程序<b class='flag-5'>內(nèi)存</b>分區(qū)!