![運行時存儲空間組織教材_第1頁](http://file3.renrendoc.com/fileroot_temp3/2022-3/6/2ae26293-4434-437f-aa6e-26d57bdaa8b5/2ae26293-4434-437f-aa6e-26d57bdaa8b51.gif)
![運行時存儲空間組織教材_第2頁](http://file3.renrendoc.com/fileroot_temp3/2022-3/6/2ae26293-4434-437f-aa6e-26d57bdaa8b5/2ae26293-4434-437f-aa6e-26d57bdaa8b52.gif)
![運行時存儲空間組織教材_第3頁](http://file3.renrendoc.com/fileroot_temp3/2022-3/6/2ae26293-4434-437f-aa6e-26d57bdaa8b5/2ae26293-4434-437f-aa6e-26d57bdaa8b53.gif)
![運行時存儲空間組織教材_第4頁](http://file3.renrendoc.com/fileroot_temp3/2022-3/6/2ae26293-4434-437f-aa6e-26d57bdaa8b5/2ae26293-4434-437f-aa6e-26d57bdaa8b54.gif)
![運行時存儲空間組織教材_第5頁](http://file3.renrendoc.com/fileroot_temp3/2022-3/6/2ae26293-4434-437f-aa6e-26d57bdaa8b5/2ae26293-4434-437f-aa6e-26d57bdaa8b55.gif)
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、運行時存儲空間組織教材6.1 靜態(tài)存儲分配靜態(tài)存儲分配 如果在編譯時就能夠確定一個程序在運行時所需的存儲空間大小,則在編譯時就能夠安排好目標(biāo)程序運行時的全部數(shù)據(jù)空間,并能確定每個數(shù)據(jù)項的單元地址,存儲空間的這種分配方法叫做靜態(tài)分配。 對FORTRAN語言來說,其特點是不允許過程有遞歸性,每個數(shù)據(jù)名所需的存儲空間大小都是常量(即不允許含可變體積的數(shù)據(jù),如可變數(shù)組),并且所有數(shù)據(jù)名的性質(zhì)是完全確定的(不允許出現(xiàn)在運行時再動態(tài)確定其性質(zhì)的名字這種情況)。這些特點確保整個程序所需數(shù)據(jù)空間的總量在編譯時是完全確定的,從而每個數(shù)據(jù)名的地址就可靜態(tài)地進(jìn)行分配。 靜態(tài)存儲分配是一種最簡單的存儲管理。一般而言,
2、適于靜態(tài)存儲分配的語言必須滿足以下條件:(1) 數(shù)組的上下界必須是常數(shù);(2) 過程調(diào)用不允許遞歸;(3) 不允許采用動態(tài)的數(shù)據(jù)結(jié)構(gòu)(即在程序運行過程中申請和釋放的數(shù)據(jù)結(jié)構(gòu))。 滿足這些條件的語言除了FORTRAN之外,還有BASIC等語言。在這些語言中,編譯程序可以完全確定程序中數(shù)據(jù)項所在的地址(通常為相對于各數(shù)據(jù)區(qū)起始地址的位移量)。由于過程調(diào)用不允許遞歸,因此數(shù)據(jù)項的存儲地址就與過程相聯(lián)系。過程調(diào)用所使用的局部數(shù)據(jù)區(qū)可以直接安排在過程的目標(biāo)代碼之后,并把各數(shù)據(jù)項的存儲地址填入相關(guān)的目標(biāo)代碼中,以便在過程運行時訪問這個局部數(shù)據(jù)區(qū)。在此,不存在對存儲區(qū)的再利用問題;目標(biāo)程序執(zhí)行時不必進(jìn)行運行
3、時的存儲空間管理,過程的進(jìn)入和退出變得極為簡單。 FORTRAN語言的靜態(tài)存儲管理特點是FORTRAN程序中的各程序段均可獨立地進(jìn)行編譯。在編譯過程中,給程序中的變量或數(shù)組分配存儲單元的一般做法是:為每一個變量(或數(shù)組)確定一個有序的整數(shù)對;其中,第一個整數(shù)用來指示數(shù)據(jù)區(qū)(局部數(shù)據(jù)區(qū)或公用區(qū))的編號,第二個整數(shù)則用來指明該變量(或數(shù)組)所對應(yīng)的存儲起始單元相對于其所在數(shù)據(jù)區(qū)起點的位移(即相對于數(shù)據(jù)區(qū)起點的地址);并將這一對整數(shù)填入符號表相應(yīng)登記項的信息欄中。至于各數(shù)據(jù)區(qū)的起始地址在編譯時可暫不確定,待各程序段全部編譯完成之后,再由連接裝配程序最終確定,并將各程序段的目標(biāo)代碼組裝成一個完整的目標(biāo)
4、程序。 一個FORTRAN程序段的局部數(shù)據(jù)區(qū)可由圖61所示的項目組成。其中,隱參數(shù)是指過程調(diào)用時的連接信息(不在源程序中明顯出現(xiàn)),如調(diào)用時的返回地址、調(diào)用時寄存器的保護(hù)等;形式單元用來存放過程調(diào)用時形參與實參結(jié)合的實參地址或值。圖61 一個FORTRAN程序段的局部數(shù)據(jù)區(qū)臨時變量數(shù)組簡單變量形式單元寄存器保護(hù)區(qū)隱參數(shù)返回地址6.2 簡單的棧式存儲分配簡單的棧式存儲分配 我們首先考慮一種簡單程序語言的實現(xiàn),這種語言沒有分程序結(jié)構(gòu),過程定義不允許嵌套,但允許過程的遞歸調(diào)用,允許過程含有可變數(shù)組。例如,C語言除不允許含有可變數(shù)組外,就是這樣一種語言。C語言的程序結(jié)構(gòu)如下:全局?jǐn)?shù)據(jù)說明main()m
5、ain中的數(shù)據(jù)說明void R()R中的數(shù)據(jù)說明void Q( )Q中的數(shù)據(jù)說明例如,下面計算n!的C語言程序就是一個遞歸調(diào)用的程序,它的執(zhí)行過程可以用棧來實現(xiàn)。# include “stdio.h”long factorial (int n)if (n1)return (n*factorial (n1);elsereturn (1);main ()int num;doscanf (“%d” , &num);if (num=0 & num =0); 6.2.1 棧式存儲分配與活動記錄 使用棧式存儲分配法意味著程序運行時,每當(dāng)進(jìn)入一個過程(或函數(shù))就有一個相應(yīng)的活動記錄累筑于棧頂
6、,此記錄含有連接數(shù)據(jù)、形式單元、局部變量、局部數(shù)組的內(nèi)情向量和臨時工作單元等;在進(jìn)入過程和執(zhí)行過程的可執(zhí)行語句之前,再把局部數(shù)組所需空間累筑于棧頂,從而形成過程工作時的完整數(shù)據(jù)區(qū)。 注意,每個過程的活動記錄的體積在編譯時可以靜態(tài)地確定。但由于允許含有可變數(shù)組,所以數(shù)組的大小只有在運行時才能知道。因數(shù)組區(qū)的大小不能預(yù)先獲知,為了擴充方便,所以只能將數(shù)組區(qū)累筑于活動記錄之上的當(dāng)前棧頂。當(dāng)一個過程工作完畢返回時,它在棧頂?shù)臄?shù)據(jù)區(qū)(包括活動記錄和數(shù)組區(qū))也隨即不復(fù)存在。 對C語言來說,由于其不含可變數(shù)組,因而它的活動記錄本身包含了局部數(shù)組的空間。圖62和圖63分別給出了C語言和含可變數(shù)組的某簡單語言程
7、序運行時的數(shù)據(jù)空間結(jié)構(gòu),即顯示了主程序在調(diào)用了過程Q,Q又調(diào)用了過程R,且在R投入運行后的存儲結(jié)構(gòu)。 SP指示器總是指向執(zhí)行過程活動記錄的起點,而TOP指示器則始終指向(已占用)棧頂單元。當(dāng)進(jìn)入一個過程時,TOP指向為此過程創(chuàng)建的活動記錄的頂端;在分配數(shù)組區(qū)之后(如果有的話),TOP又改為指向數(shù)組區(qū)(從而是該過程整個數(shù)據(jù)區(qū))的頂端。SPTOPR的活動記錄Q的活動記錄main的活動記錄全局?jǐn)?shù)據(jù)區(qū) 圖62 C語言程序的存儲組織 R的數(shù)組區(qū)R的活動記錄Q的數(shù)組區(qū)Q的活動記錄主程序全局?jǐn)?shù)據(jù)區(qū)TOPSP 圖63 含可變數(shù)組程序的存儲組織 C的活動記錄含有以下幾個區(qū)段(如圖64所示): (1) 連接數(shù)據(jù)(
8、兩項):老SP值(即前一活動記錄的起始地址)和返回地址; (2) 參數(shù)個數(shù); (3) 形式單元(存放實在參數(shù)的值或地址); (4) 過程的局部變量(簡單變量)、數(shù)組的內(nèi)情向量和臨時工作單元。圖64 C過程的活動記錄1TOP臨時工作單元內(nèi)情向量簡單變量形式單元參數(shù)個數(shù)返回地址老SPSP20 C語言不允許過程(函數(shù))嵌套,也即不允許一個過程的定義出現(xiàn)在另一個過程的定義之內(nèi)。因此,C語言的非局部變量僅能出現(xiàn)在源程序頭,非局部變量可采用靜態(tài)存儲分配并在編譯時確定它們的地址。 由圖64可知,過程的每一局部變量或形參在活動記錄中的位置都是確定的;也就是說,這些變量或形參所分配的存儲單元其地址都是相對于活動
9、記錄的基址SP的。因此,變量和形參運行時在棧上的絕對地址是:絕對地址=活動記錄基址(SP)+相對地址 于是,對當(dāng)前正在執(zhí)行(即活動)的過程,其任何局部變量或形參X的引用均可表示為變址訪問XSP。此處X代表X相對于活動記錄基址的偏移量,這個偏移量(即相對數(shù))在編譯時可完全確定下來。過程的局部數(shù)組的內(nèi)情向量的相對地址在編譯時也同樣可完全確定下來,一旦數(shù)據(jù)空間在過程里獲得分配后,對數(shù)組元素的引用也就容易用變址的方式進(jìn)行訪問。 6.2.2 過程的執(zhí)行1過程調(diào)用過程調(diào)用的四元式序列為: par T1 par T2 par Tn call P,n 由于此時TOP是指向被調(diào)用過程P之前的棧頂,而P的形式單元
10、和活動記錄起點之間的距離是確定的(等于3,參見圖64),因而由調(diào)用者過程給將要調(diào)用的過程P的活動記錄(正在形成中)的形式單元傳遞實參值或?qū)崊⒌刂?,即每個par Ti (i=1,2,n)可直接翻譯成如下指令: (i+3)TOP=Ti /*傳遞參數(shù)值*/ 或 (i+3)TOP=addrTi /*傳遞參數(shù)地址*/ 而四元式call P,n則翻譯成: 1TOP=SP /*保護(hù)現(xiàn)行SP*/ 3TOP=n /*傳遞參數(shù)個數(shù)*/ JSR P /*轉(zhuǎn)子指令,轉(zhuǎn)向P過程的第 一條指令*/過程P調(diào)用之前,先構(gòu)造出P的活動記錄部分內(nèi)容,見圖65所示。參數(shù)個數(shù)nTOP3SPT2T1現(xiàn)行SP值P的活動記錄調(diào)用過程TOP
11、43210圖65 過程P調(diào)用前先構(gòu)造P的活動記錄部分內(nèi)容 2過程進(jìn)入 轉(zhuǎn)入過程P后,首先要做的工作是定義新活動記錄的SP,保護(hù)返回地址和定義新活動記錄的TOP值,即執(zhí)行下述指令: SP= TOP+1 /*定義新SP*/ 1SP=返回地址 /*保護(hù)返回地址*/ TOP=TOP+L /*定義新TOP*/ 其中,L是過程P的活動記錄所需的單元數(shù),這個數(shù)在編譯時可靜態(tài)地計算出來。 對含可變數(shù)組(非C語言)的情況來說,因為過程可含可變數(shù)組且所有數(shù)組都分配在活動記錄的頂上,所以緊接上述指令之后應(yīng)是對數(shù)組進(jìn)行存儲分配的指令(如果含有局部數(shù)組),這些指令是在翻譯數(shù)組說明時產(chǎn)生的。對每個數(shù)組說明,相應(yīng)的目標(biāo)指令
12、組將做以下幾件工作: (1) 計算各維的上、下限; (2) 調(diào)用數(shù)組空間分配子程序,其參數(shù)是各維的上、下限和內(nèi)情向量單元首地址。 數(shù)組空間分配子程序計算并填好內(nèi)情向量的所有信息,然后在TOP所指的位置之上留出數(shù)組所需的空間,并將TOP調(diào)整為指向數(shù)組區(qū)的頂端。進(jìn)入過程P后所做的工作如圖66所示。 此后,在過程段執(zhí)行語句的工作過程中,凡引用形式參數(shù)、局部變量或數(shù)組元素都將以SP為基址進(jìn)行相對訪問。P 的數(shù)組區(qū)返回地址P的活動記錄(長度為L)1調(diào)用過程SPTOP0圖66 進(jìn)入過程P后所做的工作示意 3過程返回 C語言以及其它一些相似的語言含有return(E)形式的返回語句,其中E為表達(dá)式。假定E值
13、已計算出來并存放在某臨時單元T中,則此時即可將T值傳送到某個特定的寄存器中(調(diào)用過程將從這個特定的寄存器中獲得被調(diào)用過程P的結(jié)果)。剩下的工作就是恢復(fù)SP和TOP為進(jìn)入過程P之前的原值(即指向調(diào)用過程的活動記錄及工作空間),并按返回地址實行無條件轉(zhuǎn)移,即執(zhí)行下述指令序列: TOP= SP1 /*恢復(fù)調(diào)用過程的TOP值*/ SP=0SP /*恢復(fù)調(diào)用過程的SP值*/ X=2TOP /*將返回地址送X*/ UJ 0X /*無條件轉(zhuǎn)移,即按X的地址返回到調(diào)用過程*/ 一個過程也可通過它的end語句(對C語言則是該過程(函數(shù))體結(jié)束時的“”)自動返回。如果此過程是一個函數(shù)過程,則按上述辦法傳遞結(jié)果值,
14、否則僅直接執(zhí)行上述返回指令序列。過程P的返回示意如圖67所示。SPTOP返回地址老SPP空間調(diào)用過程空間 圖67 過程P的返回示意 6.3 嵌套過程語言的棧式實現(xiàn)嵌套過程語言的棧式實現(xiàn) 在簡單程序語言實現(xiàn)中是允許過程的遞歸調(diào)用的,并且過程中可含有可變數(shù)組?,F(xiàn)在,我們再加上一種功能,即允許過程的嵌套性。從結(jié)構(gòu)上看,PASCAL就是這樣的一種語言;但由于PASCAL含有“文件”和“動態(tài)變量”,因此,它的存儲分配不能簡單地用棧式方法來實現(xiàn)。采用PASCAL的一個子集,例如去掉“文件”和“動態(tài)變量”這種數(shù)據(jù)類型,那就可以用我們下面將要討論的方法實現(xiàn)存儲分配。 6.3.1 嵌套層次顯示表(DISPLAY
15、)和活動記錄 在討論中,常常要用到過程定義的“嵌套層次”(簡稱層數(shù))這個概念。我們始終假定主程序的層數(shù)為0,因此主程序稱為第0層過程。如果過程Q是在層數(shù)為i的過程P內(nèi)定義的,并且P是包圍Q的最小過程,則Q的層數(shù)就為i+1。當(dāng)編譯程序處理過程說明時,過程的層數(shù)將作為過程名的一個重要屬性登記在符號表中。 由于過程定義是嵌套的,因而一個過程可以引用包圍它的任一外層過程所定義的變量或數(shù)組。也就是說,運行時,一個過程Q可能引用它的任一外層過程P的最新活動記錄中的某些數(shù)據(jù)。因此,過程Q運行時必須知道它的所有外層的最新活動記錄的地址。由于允許遞歸和可變數(shù)組的存在,過程的活動記錄位置(即使是相對位置)也往往是
16、變遷的,因而必須設(shè)法跟蹤每個外層過程的最新活動記錄的位置。 一種常用的跟蹤每個外層過程最新活動記錄位置的有效辦法是,每進(jìn)入一個過程后,在建立它的活動記錄區(qū)的同時建立一張嵌套層次顯示表DISPLAY。假定現(xiàn)在進(jìn)入的過程層數(shù)為i,則它的DISPLAY表含有i+1個單元。此表本身是一個小棧,自頂而下每個單元依次存放著現(xiàn)行層、直接外層直至最外層(第0層,即主程序?qū)?的每一層的最新活動記錄的起始地址。例如,令過程R的外層為Q,Q的外層為主程序P,則過程R運行時的DISPLAY表內(nèi)容如表6.1所示。 表6.1 DISPLAY表2R的現(xiàn)行活動記錄的始址(SP的現(xiàn)行值)1Q的最新活動記錄的始址0P的活動記錄的
17、始址 由于過程的層數(shù)可靜態(tài)確定,因此每個過程的DISPLAY表的體積在編譯時即可知道。為了便于組織存儲區(qū)和簡化處理手續(xù),我們把DISPLAY作為活動記錄的一部分置于形式單元的上端,如圖68所示。 由于每個過程的形式單元數(shù)目在編譯時是知道的,因此DISPLAY的相對地址d(相對于活動記錄的起點)在編譯時也是完全確定的。被調(diào)用過程為了建立自己的DISPLAY,就必須知道它的直接外層過程的DISPLAY,這意味著必須把直接外層的DISPLAY地址作為連接數(shù)據(jù)之一(稱為“全局DISPLAY地址”)傳送給被調(diào)用過程。于是,此時的連接數(shù)據(jù)包含老SP值、返回地址和全局DISPLAY地址這三項內(nèi)容。整個活動記
18、錄的結(jié)構(gòu)如圖68所示。連接數(shù)據(jù)臨時變量內(nèi)情向量簡單變量dDISPLAY 表形式單元3參數(shù)個數(shù)2全局 DISPLAY 地址1返回地址0老SPTOPSPd個單元k第k層SP2最外層過程SP1主程序SP圖68 活動記錄結(jié)構(gòu) 6.3.2 嵌套過程的執(zhí)行 1過程調(diào)用 過程調(diào)用所做的工作與簡單棧式存儲分配大體相同,只是增加了一個連接數(shù)據(jù),所以每個par Ti 相應(yīng)的指令應(yīng)改為: (i+4)TOP=Ti 或者 (i+4)TOP=addrTi call P,n所對應(yīng)的指令應(yīng)為: 1TOP=SP /*保護(hù)現(xiàn)行SP*/ 3TOP=SP+d /*將直接外層的DISPLAY始址作為P的全局DISPLAY地址*/ 4T
19、OP=n /*傳遞參數(shù)個數(shù)*/ JSR P /*轉(zhuǎn)向P的第一條指令*/ 2過程進(jìn)入 轉(zhuǎn)入過程P后,首先執(zhí)行和簡單棧式存儲分配相同的指令: SP= TOP+1 /*定義新的SP*/ 1SP=返回地址 /*保護(hù)返回地址*/ TOP=TOP+L /*定義新的TOP*/ 其次,應(yīng)按第三項連接數(shù)據(jù)所提供的全局DISPLAY地址,自底而上地抄錄k個單元內(nèi)容(k為P的層次),最后再添上新的SP值形成現(xiàn)行過程P的DISPLAY(共k+1個單元)。其過程如圖69所示。4參數(shù)個數(shù)n3全局 DISPLAY 地址21調(diào)用過程的SPd調(diào)用過程空間P過程空間SPTOP定義新的SP;定義新的TOP;按全局DISPLAY地址
20、復(fù)制DISPLAY表至P的活動記錄;DISPLAY表圖69 過程P進(jìn)入示意 3過程返回 當(dāng)過程P工作完畢要返回到調(diào)用段時,若return語句含有返回值或P是函數(shù)過程,則把已算好的值傳送到某個特定的寄存器,然后執(zhí)行: TOP= SP1 /*恢復(fù)調(diào)用過程的TOP值*/ SP=0SP /*恢復(fù)調(diào)用過程的SP值*/ X=2TOP /*將返回地址送X*/ UJ 0X /*無條件轉(zhuǎn)移,返回*/ 過程返回執(zhí)行的指令與簡單棧式存儲分配的過程返回完全一樣。 6.3.3 訪問非局部名的另一種實現(xiàn)方法 在允許嵌套的過程中,一個過程可以引用包圍它的任一外層過程所定義的變量或數(shù)組;也即在運行時,一個過程Q可能引用它的任
21、一外層過程P的最新活動記錄中的某些數(shù)據(jù)(這些數(shù)據(jù)視為過程Q的非局部量)。為了在活動記錄中查找非局部名字所對應(yīng)的存儲空間,過程Q運行時必須知道它的所有外層過程的最新活動記錄的地址。因為過程活動記錄的位置(即使是相對位置)往往也因過程的遞歸而變遷,所以必須設(shè)法跟蹤每個外層過程的最新活動記錄的位置。 跟蹤的一種有效辦法是采用嵌套層次顯示表DISPLAY,其優(yōu)點是訪問非局部量的速度較快。在此,我們介紹另一種訪問非局部名的方法存取鏈(也稱靜態(tài)鏈)方法。 存取鏈方法引入一個稱為存取鏈的指針,該指針作為活動記錄的一項指向直接外層的最新活動記錄的地址,這就意味著在運行時棧中的每個數(shù)據(jù)區(qū)(活動記錄)之間又拉出一
22、條鏈,這個鏈稱為存取鏈。注意,運行時棧中數(shù)據(jù)區(qū)之間原先就存在一條鏈,即每個活動記 錄中所保存的老SP值這一項,它是指向調(diào)用該過程(子過程)的那個過程(父過程)的最新活動記錄的起點,由此向前形成了一條SP鏈。為了區(qū)別于存取鏈,稱SP鏈為控制鏈(也稱動態(tài)鏈),它記錄了在運行中過程之間相互調(diào)用的關(guān)系。注意,控制鏈?zhǔn)莿討B(tài)的,而存取鏈?zhǔn)庆o態(tài)的??刂奇溣涗浟水?dāng)前時刻程序中各過程相互調(diào)用的情況;而存取鏈則始終記錄著程序靜態(tài)定義時該過程所有的直接外層(嵌套過程規(guī)定,內(nèi)層過程只允許調(diào)用其靜態(tài)定義時的外層過程說明的變量和數(shù)組);因此,存取鏈指出了一個過程的當(dāng)前活動記錄指向其直接定義的外層過程直至最外層的最新活動記
23、錄的起點。具有存取鏈的活動記錄結(jié)構(gòu)如圖610所示。 假定過程的嵌套關(guān)系如下: P: var a; Q(b); var i; R; var c,d; call R; S; var c,i; call Q; call S; TOP SP臨時單元內(nèi)情向量簡單變量形式參數(shù)形參個數(shù)存取鏈(靜態(tài)鏈)返回地址控制鏈(動態(tài)鏈):老SP圖610 具有存取鏈的活動記錄結(jié)構(gòu) 程序中每個過程的靜態(tài)結(jié)構(gòu)(嵌套層次)是確定的,如嵌套深度為2的過程R引用了非局部量a和b,其嵌套深度分別為0和1。從R的活動記錄開始,分別沿著20=2和21=1個存取鏈向前查找,則可找到包含這兩個非局部量的活動記錄。 上述過程P調(diào)用S以及S調(diào)用
24、Q運行時棧的變化過程如圖611(a)、(b)所示。 由圖611可以看出,指針SP總是指向當(dāng)前正在執(zhí)行過程的活動記錄起點,控制鏈(老SP)則指向調(diào)用運行過程的父過程的活動記錄起點。因此,當(dāng)運行過程調(diào)用結(jié)束返回時,利用控制鏈老SP值可以得到調(diào)用前原父過程活動記錄的起點。從程序的靜態(tài)結(jié)構(gòu)來看,P是S和Q的靜態(tài)直接外層,所以,S和Q活動記錄中的存取鏈均指向其直接外層P的活動記錄起點。SPTOPic形參個數(shù):0存取鏈:0返回地址老SP:0a形參個數(shù):0存取鏈:0返回地址0S過程P過程i形式參數(shù):b形參個數(shù):1存取鏈:0返回地址老SPic形參個數(shù):0存取鏈:0返回地址老SP:0a形參個數(shù):0存取鏈:0返回
25、地址0TOPSPQ過程S過程P過程(b)(a)00圖611 過程調(diào)用時運行棧的變化 例6.1 某程序的結(jié)構(gòu)如圖612所示,其中A、B、C為過程名,請分別畫出過程C調(diào)用A前后的棧頂活動記錄。主程序ABC var x: int x=5 call A圖612 例6.1的程序結(jié)構(gòu)示意 解答 過程C調(diào)用A前后的棧頂活動記錄示意如圖613所示。由圖613可知,當(dāng)過程C執(zhí)行時,它可使用主程序、A、B和C過程所說明的變量,且其外層嵌套的過程活動記錄始址由DISPLAY表指出。當(dāng)C調(diào)用A而使過程A執(zhí)行時,我們看到此時的DISPLAY表已變?yōu)閮身?,即主程序和A過程自身;也即此時A只可使用主程序和A過程所說明的變量
26、。DISPLAY表A_SP主程序_SP參數(shù)個數(shù):0全局DISPLAY地址返回地址C_SP局部變量:xDISPLAY表C_SPB_SPA_SP主程序_SP參數(shù)個數(shù):0全局DISPLAY地址返回地址B_SPA_TOPA_SPC_TOPC_SP調(diào)用A后的活動記錄(在此標(biāo)記為A)調(diào)用A前C的活動記錄圖613 例6.1的運行棧與活動記錄示意 例6.2 在下面的PASCAL程序中,已經(jīng)第二次(遞歸地)進(jìn)入了f,請給出第三次進(jìn)入f后的運行棧及DISPLAY的示意圖 PROGRAM test(input, output); VAR K: integer; FUNCTION f(n: integer): int
27、eger; BEGIN IF n=0 THEN f:=1圖614 例6.2的運行棧及DISPLAY示意圖f的DISPLAY(n8)SP2SP30SP20SP100f的DISPLAY(n9)f的DISPLAY(n10)SP1test的DISPLAY第三次遞歸第二次遞歸第一次遞歸主程序SP30 解答 第三次進(jìn)入f后的運行棧及DISPLAY的示意圖如圖614所示。由于靜態(tài)嵌套層次只有兩層,故每一次遞歸調(diào)用產(chǎn)生的DISPLAY表只有兩項,一項是test的SP(即0),另一項是當(dāng)前活動記錄的SPi(i=1,2,3)。 6.4 堆式動態(tài)存儲分配堆式動態(tài)存儲分配 6.4.1 堆式存儲的概念 如果一種程序語言
28、允許數(shù)據(jù)對象能夠自由地分配和釋放,或者不僅有過程而且有進(jìn)程(process)這樣的程序結(jié)構(gòu),那么由于空間的使用不一定遵循“先申請后釋放”的原則,則棧式存儲分配就不適用了。在這種情況下,通常使用一種稱之為堆的動態(tài)存儲分配方案。假定程序運行時有一個大的存儲空間,需要時就從這個空間中借用一塊,不用時再退還給它。 由于借、還的時間先后不一,因而經(jīng)過一段時間的運行后,這個大空間就必然被分割成如圖615所示的許多小塊,這些塊有些正在使用,有些則是空閑的(未被使用)。BAC D可分配空間ABCD使用塊記錄圖615 堆式存儲分配示意 對于堆式存儲分配來說,需要解決兩個問題:一是堆空間的分配,即當(dāng)運行程序需要一
29、塊空間時應(yīng)分配哪一塊給它;另一個問題是分配空間的回收,由于返回堆的不用空間是按任意次序進(jìn)行的,所以需要研究專門的回收分配策略。 在許多語言中都有顯式的堆空間分配和回收語句或函數(shù),如PASCAL語言中的new和dispose、C語言中的alloc和free以及C+語言中的new和delete。 6.4.2 堆式存儲管理的方法 由于堆式分配方式和存儲管理技術(shù)較為復(fù)雜,并且有效的堆管理是數(shù)據(jù)結(jié)構(gòu)課程研究的問題,故我們只對堆式分配方式作簡單的討論。 當(dāng)運行程序要求一塊體積為N的存儲空間時應(yīng)如何分配?從理論上講,這時應(yīng)從比N稍大一些的空閑塊中取出N個單元予以分配,這種做法的目的是保持較大的空閑塊以備將來
30、之需。但這種方法實現(xiàn)起來難度較大,實際中采用的辦法是:掃描空閑塊鏈并在首次遇到的比N大的空閑塊中取出N個單元進(jìn)行分配。 如果找不到一塊比N大的空閑塊,但所有空閑塊的總和卻比N大,這時就需要用某種方法使這些空閑塊拼接在一起,形成一個可分配的連續(xù)空間。如果所有空閑塊的總和都不及N大,則需要采用更復(fù)雜的辦法,如廢品回收技術(shù)(即尋找那些運行程序已不使用但仍未釋放的存儲塊或運行程序目前很少使用的存儲塊),把這些存儲塊回收后再重新分配。 可以采用多種策略進(jìn)行堆式動態(tài)存儲管理。在此,我們介紹一種使用可利用空間表進(jìn)行動態(tài)分配的方法。可利用空間表是指將所有空閑塊用一張表記錄下來,表的結(jié)構(gòu)可以是目錄表,也可以是鏈
31、表,其結(jié)構(gòu)分別如圖616(b)、(c)所示。050012001700200026003600(a)塊編號起始地址 內(nèi)存大小150070021700300326001000heap7003001000(b)50017002600(c)圖616 內(nèi)存狀態(tài)和可利用空間表 使用可利用空間表進(jìn)行動態(tài)存儲分配的方法又可分為如下兩種: (1) 定長塊的管理。最簡單的堆式存儲管理方法是采用定長塊的管理方法,即將堆存儲空間在初始化時就劃分成大小相同的若干塊,將各個塊通過鏈表鏈接起來形成一個單向線性鏈表。由于各塊大小相同,故分配時無需查找,只需將頭指針?biāo)傅牡谝粔K分配給用戶即可,然后頭指針指向下一塊。同樣,當(dāng)回收
32、時,系統(tǒng)將待回收的存儲塊插入到表頭即完成了該塊的回收。 (2) 變長塊的管理。變長塊管理方法是一種常用的堆式存儲管理方法,它可以根據(jù)實際需要來分配長度不同的空閑塊;對空閑塊的管理則可以采用圖616(c)中的鏈表形式。 系統(tǒng)開始時,存儲空間是一完整空間,可利用空間表中只有一個大小為整個存儲空間的空閑塊。當(dāng)系統(tǒng)運行一段時間后,隨著分配和回收的進(jìn)行,可利用空間表中空閑塊的大小和個數(shù)也隨之改變。由于可利用空間表中的空閑塊大小不同,因而存在著如何進(jìn)行空閑塊分配的問題。若可利用空間表存在多個大于所要求空間的空閑塊,可采取以下三種方法之一進(jìn)行存儲分配: (1) 首次滿足法。從表頭開始查找可利用空間表,將找到
33、的第一個滿足需要的空閑塊或空閑塊的一部分分配出去(當(dāng)空閑塊略大于所要求的空間時,則整塊分配出去),而其余部分仍作為一個空閑塊留在表中。 (2) 最優(yōu)滿足法。系統(tǒng)掃描整個可利用空間表,從中找出一塊不小于要求的最小空閑塊予以分配。為了避免每次分配都要掃描整個表,通常將空閑塊按由小到大的順序進(jìn)行排列。這樣,所找到的第一個大于或等于所需空間的空閑塊即為所求,無須再掃描整個表。 (3) 最差滿足法。系統(tǒng)將可利用空間表中最大的空閑塊予以分配(當(dāng)然也要求其不小于所需空間的大小),這種方法應(yīng)使空閑塊按由大到小的順序排列,此時表頭的空閑塊即為所求。 最優(yōu)滿足法和最差滿足法在回收時都需將待回收的空閑塊插入到鏈表中
34、適當(dāng)?shù)奈恢蒙先ァ?以上三種方法各有所長。一般來說,最優(yōu)滿足法適用于請求分配的內(nèi)存大小范圍較廣的系統(tǒng);最差滿足法適用于請求分配的內(nèi)存大小范圍較窄的系統(tǒng);而首次滿足法則適用于事先無法獲知請求分配和回收情況的系統(tǒng)。從時間上來看,最優(yōu)滿足法無論分配與回收都需要查表,故最費時間;最差滿足法分配時無需查表,但回收時卻需查表并根據(jù)回收空閑塊的大小確定其在表中應(yīng)插入的位置;而首次滿足法在分配時需要查表,回收時直接插入到表頭即可。 對于已分配的存儲塊,可以采用不同的回收策略。有的程序語言干脆不做回收工作,直到內(nèi)存空間用完為止;如果當(dāng)空間用完后還有分配存儲塊的請求,就停止程序的運行。這樣做的缺點是浪費空間,但如果
35、系統(tǒng)具有海量虛存或堆中的多數(shù)數(shù)據(jù)是一分配就一直使用的情形,則這種方法也是可行的。如果程序語言有顯式的分配命令,那么就可用顯式的回收命令(如C語言中的free)來回收不用的空間。*6.5 參數(shù)傳遞補遺參數(shù)傳遞補遺 定義和調(diào)用過程是程序語言的主要特征之一。過程是模塊程序設(shè)計的主要手段,同時也是節(jié)省程序代碼和擴充語言能力的主要途徑。PASCAL語言的設(shè)計者N.Wirth曾經(jīng)說過:“在程序設(shè)計技巧中,過程是很少幾種基本工具中的一種,掌握了這種工具,就能對程序員工作的質(zhì)量和風(fēng)格產(chǎn)生決定性的影響”。 一個過程一旦定義后,就可以在別的地方調(diào)用它。調(diào)用與被調(diào)用(過程)兩者之間的信息往來通過全局量或參數(shù)傳遞。例
36、如,下面的C語言程序: #include “stdio.h” void showme (int a, int b, int c) printf (“a=%d, b=%d, c=%dn”, a, b, c); main () int x=10, y=20, z=30; showme (z, y, x); 就是一個含函數(shù)調(diào)用的程序。其中a、b、c稱為形式參數(shù)(簡稱形參),而函數(shù)調(diào)用語句:showme (z, y, x) 中的z、y、x則稱為實在參數(shù)(簡稱實參)。實參甚至也可以是一個較復(fù)雜的表達(dá)式而不僅僅只是一個變量。實參和對應(yīng)的形參在性質(zhì)上應(yīng)相容不悖。 6.5.1 參數(shù)傳遞的方法 形式參數(shù)提供了參
37、數(shù)替換的手段,在過程調(diào)用時可以使用不同的數(shù)據(jù)作為實在參數(shù)來替換形式參數(shù),從而實現(xiàn)了同一個過程可以對不同的實在參數(shù)進(jìn)行相同操作的功能。那么,如何把實在參數(shù)傳遞給相應(yīng)的形式參數(shù)呢?程序語言中參數(shù)傳遞的方式主要有傳值(call by value)、傳地址(call by reference)和傳名(call by name)三種。 1傳值 傳值是最簡單的參數(shù)傳遞方法。所謂傳值,就是計算出實在參數(shù)的值然后把它傳給被調(diào)用過程相對應(yīng)的形式參數(shù),具體過程如下: (1) 把形式參數(shù)當(dāng)作過程的局部變量處理,即在被調(diào)用過程的活動記錄中開辟形式參數(shù)的存儲空間(即形式單元)。 (2) 調(diào)用過程計算出實在參數(shù)的值,并將
38、該值放入為形式單元開辟的空間中。 (3) 被調(diào)用過程執(zhí)行時就像使用局部變量一樣使用這些形式單元。 傳值的一個重要特點是對形式參數(shù)的任何運算都不影響調(diào)用過程的活動記錄中實在參數(shù)的值,即參數(shù)傳遞后實在參數(shù)與對應(yīng)的形式參數(shù)不再發(fā)生聯(lián)系了。 2傳地址 所謂傳地址,是指把實在參數(shù)的地址傳遞給相應(yīng)的形式參數(shù)所對應(yīng)的形式單元。如果實在參數(shù)是一個變量(包括下標(biāo)變量),則直接將該變量的地址傳給相應(yīng)的形式單元;如果實在參數(shù)是常數(shù)或表達(dá)式,則先計算其值并存放在某一臨時單元中,然后將這個臨時單元的地址傳給相應(yīng)的形式單元。被調(diào)用過程執(zhí)行時,對形式參數(shù)的任何引用或賦值都被處理成對形式單元的間接訪問,即按形式單元中存放的地址轉(zhuǎn)到調(diào)用過程的活動記錄中去訪問實在參數(shù)。 對
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 金融租賃居間合同模板
- 始興縣中醫(yī)院特殊用房設(shè)施設(shè)備采購及安裝及醫(yī)療設(shè)備采購項目招標(biāo)文件
- 終止合同退款協(xié)議
- 未維修事故車買賣合同協(xié)議書
- 企業(yè)人才培養(yǎng)與發(fā)展作業(yè)指導(dǎo)書
- 質(zhì)押礦產(chǎn)權(quán)收益權(quán)擔(dān)保協(xié)議書
- 養(yǎng)雞業(yè)養(yǎng)殖技術(shù)手冊
- 庫房轉(zhuǎn)租合同
- 智能倉儲標(biāo)準(zhǔn)化管理與供應(yīng)鏈優(yōu)化項目實踐
- 焊接結(jié)構(gòu)分析與優(yōu)化作業(yè)指導(dǎo)書
- 校本課程《生活中的化學(xué)》教案
- 寶典三猿金錢錄
- 安徽凌瑋新材料科技有限公司年產(chǎn)2萬噸超細(xì)二氧化硅氣凝膠系列產(chǎn)品項目環(huán)境影響報告書
- 聚合物粘彈性
- 建筑工程施工現(xiàn)場安全資料管理規(guī)程解讀
- 華銀鋁項目氧化鋁系統(tǒng)總體投料試車方案
- 2023年衛(wèi)生院崗位大練兵大比武競賽活動實施方案
- 2023年浙江省初中學(xué)生化學(xué)競賽初賽試卷
- 遼海版小學(xué)五年級美術(shù)下冊全套課件
- 專題7閱讀理解之文化藝術(shù)類-備戰(zhàn)205高考英語6年真題分項版精解精析原卷
- 2022年廣東省10月自考藝術(shù)概論00504試題及答案
評論
0/150
提交評論