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

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

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

關(guān)于堆棧的深入理解

0BFC_eet_china ? 來源:未知 ? 作者:鄧佳佳 ? 2018-03-04 15:57 ? 次閱讀

一、這些個(gè)概念怎么來的以及怎么記得住

這里,只限于整理我個(gè)人對(duì)堆/棧/堆棧在內(nèi)存管理方面的理解。其他,在數(shù)據(jù)結(jié)構(gòu)方面講的堆/棧目前不在我整理范圍之內(nèi)。

這里提了三個(gè)概念: 堆,棧,以及堆棧。我把棧和堆棧的概念等同了。所以,接下來只要把兩個(gè)概念弄清楚就可以了:堆和棧。

先說由來。由于我的工作大部分是和單片機(jī)相關(guān)的,因此也是基于嵌入式的這個(gè)方面的理解。

每片MCU有一定的內(nèi)存,這些內(nèi)存分:程序存儲(chǔ)區(qū);數(shù)據(jù)存儲(chǔ)區(qū)。舉例就是:我們寫的每行代碼,都會(huì)保存到程序存儲(chǔ)區(qū)里面;而定義的一些全局變量,靜態(tài)變量,局部變量之類的,就保存到數(shù)據(jù)存儲(chǔ)區(qū)。

程序存儲(chǔ)區(qū),對(duì)于寫代碼的人來說,可以說是黑盒子:只要你的代碼不超過程序代碼空間,everything will be fine. 代碼究竟是如何執(zhí)行的,取決于你的編程思想,就是說,你讓程序往東走,它就會(huì)往東走;讓它原地踏步,它也會(huì)照做;前提是你的代碼要寫好。所以,對(duì)于編程經(jīng) 驗(yàn)成熟的人,同樣的算法,他可能會(huì)少敲幾行代碼,并且算法出錯(cuò)的幾率少一些;不怎么會(huì)編程的人,就多敲幾行,多測(cè)試一下。研究深一些的人,可能還會(huì)對(duì)代碼 執(zhí)行效率深入研究。我決定就此止步。繼續(xù)黑盒子的話題,程序員的代碼會(huì)燒寫到程序存儲(chǔ)區(qū)里面,至于哪條語(yǔ)句存哪里,這個(gè)是不用研究的。反正,一旦發(fā)現(xiàn)軟件 沒按照你設(shè)計(jì)的那樣跑,基本就是程序自身的問題,不是存放程序的存儲(chǔ)區(qū)的問題。

數(shù)據(jù)存儲(chǔ)區(qū),讓程序員發(fā)揮的空間就很大了。由于程序是動(dòng)態(tài)地執(zhí)行的,執(zhí)行的結(jié)果是怎么樣,會(huì)產(chǎn)生什么數(shù)據(jù)就不是一個(gè)確定的事情。

舉個(gè)例子說說這個(gè)程序和數(shù)據(jù)之間的表象吧。舉例的事件就是:一個(gè)MP3播放器的上/下鍵的操作。加入在播放器里有10首歌,若當(dāng)前是第3首,那 么按下[上]鍵后,應(yīng)該是播放第2首。因此,實(shí)現(xiàn)播放第2首的,就是程序員寫程序?qū)崿F(xiàn)的,他的代碼讓[上]鍵實(shí)現(xiàn)了能從第3首切換到第2首的操作。這里, 表現(xiàn)的就是代碼。而且,這個(gè)代碼是確切的行為,從第3首按了[上]鍵之后,一定是播放到第2首。這個(gè)是確切的行為,如果不能實(shí)現(xiàn),就是代碼有bug了,需 要改正。終于可以扯到數(shù)據(jù)了。第2首是什么歌呢? 就是說第2首歌的內(nèi)容是什么呢? 當(dāng)然在程序員寫代碼的時(shí)候,他是不知道的,他要做的,就是預(yù)先開一片數(shù)據(jù)空間,以存放歌曲相關(guān)的數(shù)據(jù)。這片數(shù)據(jù)空間,想放什么就放什么,是靈活的。聽煩了 這幾首歌以后,再更換其它音頻文件就是了。再說具體一點(diǎn),程序就相當(dāng)于修的一條路,讓車可以在上面跑;但車上面裝了什么,程序員是不知道的。

堆和棧屬于數(shù)據(jù)存儲(chǔ)區(qū)的范疇,也可以算是數(shù)據(jù)管理的手段或方法?;诖?,不能一概而論,說哪個(gè)手段高明一些;他們也是基于現(xiàn)實(shí)的需要而產(chǎn)生的。黑格爾說:存在就是合理的。

這樣的概念大家都不陌生:軍隊(duì)的管理是很嚴(yán)格的,很死板的;但是對(duì)于一些年輕的技術(shù)公司來說,員工就享有很高的自由度。

如果我說,墻角邊整齊地?cái)[放著10本書; 以及墻角邊的書凌亂地放著。你閉上眼睛,能區(qū)分出兩種畫面嗎? 如果沒有,就不用往下看了。

棧的特性,就是嚴(yán)格/有序/規(guī)范的。棧的英文就是Stack. 如果我說,there are books stacked in that corner,你應(yīng)該能知道書是怎么放的吧。

相反,堆呢,就是自由/靈活/隨意的。堆的英文是Heap. 如果我說,there are books heaped in that corner,你應(yīng)該能知道書是怎么放的吧。

二、get closer to the real STACK/HEAP。

棧: 由系統(tǒng)自動(dòng)分配和回收的。

堆: 由程序員分配和回收的。

基于第一部分的理解,不用想都知道,作為“堆”的數(shù)據(jù)空間,也必須是靈活的,因?yàn)槌汕先f(wàn)的程序員在寫什么程序是未知的。但可知道的一點(diǎn),就是他們是跑在確定的某個(gè)OS里面的。

因此,也不過就是給系統(tǒng)管理的數(shù)據(jù)空間起了個(gè)名字,就棧;給程序員使用的空間,起了個(gè)名,就堆。

我接下來就會(huì)廢話:起什么名字都不重要,重要的是,我們得對(duì)這兩種數(shù)據(jù)存儲(chǔ)區(qū)的管理的機(jī)制由來,方法有深刻認(rèn)識(shí);這樣,即便幾個(gè)世紀(jì)以后它們更名為阿貓阿狗了,我們依然能認(rèn)知它們。

舉例:

void Check_Pro_Code( uint8 style )

{

uint8 i;

switch( style )

{

......

}

}

void main( )

{

uint8 j = 1;

Check_Pro_Code( j );

}

在main()函數(shù)里調(diào)用了Check_Pro_Code(...)函數(shù),事先要對(duì)j進(jìn)行入棧操作;當(dāng)然這里函數(shù)調(diào)用的時(shí)候,涉及到幾個(gè)入棧操作:程序的下一個(gè)執(zhí)行地址;局部變量;形參。

這里,我就沒有深入介紹了。

實(shí)在很慚愧的是,我寫的嵌入式軟件里,沒有涉及到任何和堆操作相關(guān)的。我就是那樣一個(gè)人,CM3內(nèi)核里也沒有移植操作系統(tǒng),實(shí)在是汗顏,因?yàn)楸救藢?duì)RTOS實(shí)在是未曾涉獵。所以,我這里對(duì)于堆的介紹,是沒有任何實(shí)戰(zhàn)鷹眼的。并且為了堆我就堆了一下。你說,這樣算學(xué)術(shù)造假嗎?

void main( )

{

int j=10;

int *p;

p = malloc( 10 ); //話說這里就是堆,我是為了用而用,實(shí)在是無味地很。

p = "123456".

}

三、話說堆棧溢出

再次明確,堆棧溢出的堆棧是指棧。

1 當(dāng)C程序函數(shù)的調(diào)用層次過深或者出現(xiàn)了遞歸調(diào)用,就容易使程序運(yùn)行所需的堆棧空間超過系統(tǒng)能提供的最大堆??臻g范圍,產(chǎn)生堆棧溢出。

這是很明白的,當(dāng)A函數(shù)調(diào)用了B函數(shù),而B()里面又調(diào)用了C(),C()里又調(diào)用了D()......當(dāng)這樣的調(diào)用太深的時(shí)候,就容易堆棧溢出了。

四、一級(jí)緩存/二級(jí)緩存

棧使用的是一級(jí)緩存, 他們通常都是被調(diào)用時(shí)處于存儲(chǔ)空間中,調(diào)用完畢立即釋放。

堆則是存放在二級(jí)緩存中,生命周期由虛擬機(jī)的垃圾回收算法來決定(并不是一旦成為孤兒對(duì)象就能被回收)。所以調(diào)用這些對(duì)象的速度要相對(duì)來得低一些。

棧的優(yōu)勢(shì)是,存取速度比堆要快,僅次于直接位于CPU中的寄存器。

舉個(gè)我知道的例子:

void main( )

{

int i,j;

static int flag = 1;

i = Sum_Of_Group( );

j = Check_Exist( );

}

這里,i,j的值都是給通用寄存器的,而不是給予確切的物理地址。而對(duì)于flag,由于其為靜態(tài)變量,是在SRAM里面分配地址的。這里好像沒有說到一級(jí)緩存二級(jí)緩存。時(shí)間限制,下回述。

五、棧:在Windows下,棧是向低地址擴(kuò)展的數(shù)據(jù) 結(jié)構(gòu),是一塊連續(xù)的內(nèi)存的區(qū)域。這句話的意思是棧頂?shù)牡刂泛蜅5淖畲笕萘渴窍到y(tǒng)預(yù)先規(guī)定好的,在 WINDOWS下,棧的大小是2M(也有的說是1M,總之是一個(gè)編譯時(shí)就確定的常數(shù)),如果申請(qǐng)的空間超過棧的剩余空間時(shí),將提示overflow。因 此,能從棧獲得的空間較小。

堆:堆是向高地址擴(kuò)展的數(shù)據(jù)結(jié)構(gòu),是不連續(xù)的內(nèi)存區(qū)域。這是由于系統(tǒng)是用鏈表來存儲(chǔ)的空閑內(nèi)存地址的,自然是不連續(xù)的,而鏈表的遍歷方向是由低地址向高地址。堆的大小受限于計(jì)算機(jī)系統(tǒng)中有效的虛擬內(nèi)存。由此可見,堆獲得的空間比較靈活,也比較大。

注:該段內(nèi)容100%抄襲,出處:網(wǎng)絡(luò)。

六、如何修改我自己的工程的STACK(以下內(nèi)容不通用)

由于我自己的工程用的是LPC1765,剛好從網(wǎng)絡(luò)抄到了比較有用的圖片。摘于此。其他單片機(jī)的編譯環(huán)境,應(yīng)該也是差不多如法炮制的。

編譯環(huán)境: IAR for ARM.

圖一 :如何修改STACK的大小

圖二,如何知道自己的工程用了多少堆棧

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

    關(guān)注

    0

    文章

    182

    瀏覽量

    19708

原文標(biāo)題:關(guān)于堆棧的深入理解

文章出處:【微信號(hào):eet-china,微信公眾號(hào):電子工程專輯】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    深入理解FPD-link III ADAS解串器HUB產(chǎn)品

    電子發(fā)燒友網(wǎng)站提供《深入理解FPD-link III ADAS解串器HUB產(chǎn)品.pdf》資料免費(fèi)下載
    發(fā)表于 09-06 09:58 ?0次下載
    <b class='flag-5'>深入理解</b>FPD-link III ADAS解串器HUB產(chǎn)品

    堆棧和內(nèi)存的基本知識(shí)

    本文主要聊聊關(guān)于堆棧的內(nèi)容。包括堆棧和內(nèi)存的基本知識(shí)。常見和堆棧相關(guān)的 bug,如棧溢出,內(nèi)存泄漏,堆內(nèi)存分配失敗等。后面介紹軟件中堆棧統(tǒng)計(jì)
    的頭像 發(fā)表于 08-29 14:10 ?322次閱讀
    <b class='flag-5'>堆棧</b>和內(nèi)存的基本知識(shí)

    錫焊原理解析:深入理解電子產(chǎn)品制造的核心工藝

    探索焊接技術(shù)在精密電子工程中的重要性和創(chuàng)新,從基礎(chǔ)元件的連接到現(xiàn)代焊接技術(shù)的進(jìn)展,深入了解焊接材料的選擇與焊接技術(shù)的分類。本文提供了對(duì)錫焊原理的深入分析,揭示了高質(zhì)量電子產(chǎn)品制造的關(guān)鍵因素。
    的頭像 發(fā)表于 08-12 15:03 ?434次閱讀
    錫焊原<b class='flag-5'>理解</b>析:<b class='flag-5'>深入理解</b>電子產(chǎn)品制造的核心工藝

    深入理解FFmpeg閱讀體驗(yàn)》

    一、編譯X264 H.264是ITU(International Telecommunication Union,國(guó)際通信聯(lián)盟)和MPEG(Motion Picture Experts Group,運(yùn)動(dòng)圖像專家組)聯(lián)合制定的視頻編碼標(biāo)準(zhǔn)。而X264是一個(gè)開源的H.264/MPEG-4 AVC視頻編碼函數(shù)庫(kù),是最好的有損視頻編碼器之一。 先直接從網(wǎng)絡(luò)(http://download.videolan.org/pub/videolan/x264/snapshots/)獲取X264源碼??紤]到版本關(guān)系,本文我下載的是x264-snapshot-20180430-2245-stable.tar.bz2。 tar -vxf x264-snapshot-20180430-2245-stable.tar.bz2 mkdir x264 手動(dòng)創(chuàng)建的X264文件夾用于存放編譯后的X264庫(kù)。執(zhí)行如下命令: ./configure --host=aarch64-linux --prefix=/home/x264 --enable-shared --disable-asm --enable-static --cross-prefix=aarch64-linux-gnu- 之后執(zhí)行make make install完成x264庫(kù)的交叉編譯。生成的文件信息如下: root@EliteDesk800:~/x264/lib$ ls libx264.solibx264.so.152pkgconfig root@EliteDesk800:~/x264/lib$ file * libx264.so:symbolic link to libx264.so.152 libx264.so.152: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, BuildID[sha1]=01dd733d65c98eb894b4cdd41216259543ec8405, with debug_info, not stripped pkgconfig:directory 二、編譯FFmpeg 首先從FFmpeg官方網(wǎng)站http://ffmpeg.org/download.html上下載FFmpeg源碼。 tar -vxf ffmpeg-snapshot.tar.bz2 mkdir ffmpeg_install 其中ffmpeg_install文件夾用于保存生成的文件。執(zhí)行如下命令: ./configure --prefix=/home/ffmpeg_install --enable-cross-compile --arch=arm64 --target-os=linux --cc=aarch64-linux-gnu-gcc --disable-x86asm --cross-prefix=aarch64-linugnu---pkg-config=/usr/bin/pkg-config --pkg-config=/usr/bin/pkg-config主要用于解決ERROR: x264 not found using pkg-config問題,網(wǎng)上很多解決方法都不靠譜。 之后執(zhí)行make make install完成ffmpeg的交叉編譯。 生成的文件信息如下: root@EliteDesk800:~/ffmpeg$ file ../ffmpeg_install/bin/* ../ffmpeg_install/bin/ffmpeg:ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, for GNU/Linux 3.7.0, BuildID[sha1]=b32285f11866f79dd499330849a9b3195ea0e446, stripped ../ffmpeg_install/bin/ffprobe: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, for GNU/Linux 3.7.0, BuildID[sha1]=5d3fa4ea21ad6c4395bbaf134b915190799305b2, stripped
    發(fā)表于 04-16 22:54

    深入理解 Sora 的技術(shù)原理

    將去除噪音后的結(jié)果數(shù)據(jù),利用視頻解碼器進(jìn)行解碼,將低維潛在空間數(shù)據(jù)還原成原始視頻數(shù)據(jù),這里可以實(shí)現(xiàn)不同分辨率的視頻解碼。
    的頭像 發(fā)表于 04-05 09:19 ?1836次閱讀
    <b class='flag-5'>深入理解</b> Sora 的技術(shù)原理

    深入理解 FPGA 的基礎(chǔ)結(jié)構(gòu)

    轉(zhuǎn)載地址:https://zhuanlan.zhihu.com/p/506828648 文章很詳細(xì)的介紹了FPGA的基礎(chǔ)結(jié)構(gòu),能更直觀的理解內(nèi)部結(jié)構(gòu)原理。對(duì)深入學(xué)習(xí)很有幫助。 以下是正文: 這一段
    發(fā)表于 04-03 17:39

    深入理解數(shù)據(jù)備份的關(guān)鍵原則:應(yīng)用一致性與崩潰一致性的區(qū)別

    深入理解數(shù)據(jù)備份的關(guān)鍵原則:應(yīng)用一致性與崩潰一致性的區(qū)別 在數(shù)字化時(shí)代,數(shù)據(jù)備份成為了企業(yè)信息安全的核心環(huán)節(jié)。但在備份過程中,兩個(gè)關(guān)鍵概念——應(yīng)用一致性和崩潰一致性,常常被誤解或混淆。本文旨在闡明
    的頭像 發(fā)表于 03-11 11:29 ?748次閱讀
    <b class='flag-5'>深入理解</b>數(shù)據(jù)備份的關(guān)鍵原則:應(yīng)用一致性與崩潰一致性的區(qū)別

    深入理解GPIO原理和運(yùn)用

    GPIO允許我們的單片機(jī)與外部世界進(jìn)行通信,它是我們控制外部設(shè)備和接收外部信號(hào)的接口。
    的頭像 發(fā)表于 02-19 16:12 ?1739次閱讀
    <b class='flag-5'>深入理解</b>GPIO原理和運(yùn)用

    恒訊科技帶大家深入理解:WebSocket服務(wù)器的工作原理

    WebSocket是一種在單個(gè)TCP連接上進(jìn)行全雙工通信的通信協(xié)議。它的設(shè)計(jì)目標(biāo)是在Web瀏覽器和服務(wù)器之間提供低延遲、高效的雙向通信。下面是深入理解WebSocket服務(wù)器工作原理的一些關(guān)鍵概念
    的頭像 發(fā)表于 01-29 16:48 ?405次閱讀

    深入理解光耦模擬隔離放大電路的技術(shù)奧秘

    深入理解光耦模擬隔離放大電路的技術(shù)奧秘 ?編輯 ▲ 圖1 仿真原理圖二、原理分析 之所以這個(gè)電路圖看起來容易讓人感到困惑,實(shí)際上就是這個(gè)仿真電路中,錯(cuò)誤的使用了這樣的光電三極管來表示HCNR201
    發(fā)表于 01-10 10:12

    深入理解FFmpeg閱讀體驗(yàn)》初識(shí)有感

    【感謝】 這兩年來,多有接觸到有關(guān)視頻的處理方法,特別是想把mp4轉(zhuǎn)換為gif,我搜索到FFmpeg是可以轉(zhuǎn)換的,而且速度及快。再有就是很多的嵌入式開發(fā)板可以快速用FFmpeg來生成視頻流。這次論壇恰好有這么好的機(jī)會(huì),當(dāng)然也有緣份讓我有幸成為試讀者,特此感謝電子發(fā)燒友論壇。 【初識(shí)有感】 我今天剛拿到的書,認(rèn)真的閱讀了推薦語(yǔ)、序、前言這幾篇,讓我深有感觸。 第一,通過這幾篇我得知?jiǎng)⑵缋蠋?,是一位正真正開源的大師,他能在工作之余,把FFmpeg鉆研這么透,并積極的參與開源項(xiàng)目的推廣,劉老師在很多年前編寫了《FFmpeg從入門到精通》,給想入門FFmpeg的人打開了一扇大門。 第二,在前言中《如何閱讀本書》指出我們?nèi)绾伍_始學(xué)習(xí)FFmpeg。老師建議從頭開始,上篇為基礎(chǔ)篇,下篇為API使用以及開發(fā)。 第三,書中還給我們指出如何從FFmpeg官方文檔、wiki以及推薦雷霄驊博士的學(xué)習(xí)資料。 經(jīng)過閱讀前面幾章,讓我感覺入門FFmpeg應(yīng)該學(xué)習(xí)資料非常之多,只要認(rèn)真的學(xué)習(xí),應(yīng)該可以掌握這門技術(shù)。
    發(fā)表于 01-07 19:48

    深入理解FFmpeg閱讀體驗(yàn)》+ 書收到了,嶄新的開篇

    今天收到了《深入理解FFmpeg》 嶄新的書,一個(gè)在2022年較近距離接觸過卻尚未深入研究的領(lǐng)域圖像處理。最近剛好在作這方面的研究,希望自己可以把握這次機(jī)會(huì),好好學(xué)習(xí)下 FFMpeg,相信可以讓自己
    發(fā)表于 01-07 18:57

    深入理解BigBird的塊稀疏高效實(shí)現(xiàn)方案

    RoBERTa 架構(gòu)的 BigBird 模型現(xiàn)已集成入 transformers 中。本文的目的是讓讀者 深入 了解 BigBird 的實(shí)現(xiàn),并讓讀者能在 transformers 中輕松
    的頭像 發(fā)表于 11-29 11:02 ?499次閱讀
    <b class='flag-5'>深入理解</b>BigBird的塊稀疏高效實(shí)現(xiàn)方案

    【書籍評(píng)測(cè)活動(dòng)NO.25】深入理解FFmpeg,帶你FFmpeg從入門到精通

    ,涵蓋音視頻基礎(chǔ)知識(shí)、FFmpeg參數(shù)解析、API使用、內(nèi)部組件的開發(fā)定制 行業(yè)大咖審校,多名業(yè)界專家與學(xué)者作序推薦 詳細(xì)解讀實(shí)際應(yīng)用與開發(fā)案例,幫助讀者深入理解FFmpeg 大咖推薦 我
    發(fā)表于 11-15 14:26

    深入理解TCP

    當(dāng)客戶端想和服務(wù)端建立 TCP 連接的時(shí)候,首先第一個(gè)發(fā)的就是 SYN 報(bào)文,然后進(jìn)入到 SYN_SENT 狀態(tài)。 在這之后,如果客戶端遲遲收不到服務(wù)端的 SYN-ACK 報(bào)文(第二次握手),就會(huì)觸發(fā)超時(shí)重傳機(jī)制。 不同版本的操作系統(tǒng)可能超時(shí)時(shí)間不同,有的 1 秒的,也有 3 秒的,這個(gè)超時(shí)時(shí)間是寫死在內(nèi)核里的,如果想要更改則需要重新編譯內(nèi)核,比較麻煩。 當(dāng)客戶端在 1 秒后沒收到服務(wù)端的 SYN-ACK 報(bào)文后,客戶端就會(huì)重發(fā) SYN 報(bào)文,那到底重發(fā)幾次呢? 在 Linux 里
    的頭像 發(fā)表于 11-08 16:37 ?485次閱讀
    <b class='flag-5'>深入理解</b>TCP