目錄:1. 記憶體池
2. 棧
3. hash表
1.記憶體池
在一些小的程式裡,沒什麼必要新增記憶體管理模組在裡面。但是對於比較複雜的**,如果需要很多的記憶體操作,那麼加入自己的記憶體管理是有必要的。至少有一些好處:能夠加快記憶體的申請和釋放;能夠輕鬆的查詢記憶體洩露問題;能夠對整個軟體的記憶體消耗做乙個比較精確的統計;對以後的優化有很大的好處等等。所以,在我的直譯器裡,我加入了乙個簡單的記憶體管理模組,仿造了記憶體池的做法。
主要思想是這樣的:
a.記錄所有的申請的記憶體
b.當釋放記憶體時,記錄下來以供下次申請使用
c.申請記憶體時,可以直接使用前面釋放過的記憶體
為了達到以上的功能。我為申請記憶體的大小劃分粒度,例如:我得粒度這麼安排那麼申請17個位元組的大小時候,我會申請32個位元組的大小。這樣子方便管理。並且為每個粒度建立乙個可用記憶體的雙向鍊錶。申請記憶體時,就可直接從這些煉表頭中申請(即將乙個節點從煉表頭移除,作為被申請的空間,並插入到在使用的鍊錶中),記憶體的釋放則是乙個想法的過程。這些的儲存結構如下所示:
(圖1.1 記憶體池的儲存結構)
typedef struct _pool_blockpool_block_t;
typedef struct _poolpool_t;
int pool_atom_tab[pool_atom_num] = ;
說明:a.記憶體的申請會按照pool_atom_tab陣列中的大小對齊,比如申請10byte,那麼,我會申請32byte.
b.為每個粒度儲存乙個雙向鍊錶,用於儲存被釋放的記憶體。如果要申請的記憶體超過8192,那麼我直接呼叫系統的malloc,釋放時,直接呼叫free.
c.記憶體申請過程:到相應的粒度鍊錶(list_free)中檢視是否有可用記憶體,如果有,直接將它從該list_free鍊錶中移動到list_all鍊錶。
d.記憶體釋放過程:要釋放的記憶體必定儲存在list_all中,根據它的大小,把它移動到相應的list_free鍊錶。
e.pool_block_t結構被放置在申請記憶體的前面,則在釋放時,直接根據buffer指標就可得到pool_block_t的位置,從而得到next和pre,快速的在鍊錶中移動。
2.棧
棧在直譯器中用到的地方很多,不管是表示式的解析,還是**塊的解析,型別的解析,等等都用到了棧。所以不實現它是不可能的事,不過在資料結構中他是最簡單的了,無非就是申請乙個空間,按乙個乙個的節點儲存進去,按乙個乙個的節點取出來。沒什麼技巧在裡面,只是這個我讓棧的大小空間是自動增長和減小的,這麼做的目的是:棧的空間僅僅限制於記憶體的大小。但是,這麼做得缺點是,當棧的空間大小自動變化時,棧內的資料要被複製一遍,這務必會影響效率。但沒有辦法,暫時之能這樣了。唯一的辦法是在時間和空間上做乙個選擇。
棧的儲存結構如下:
(圖1.2 棧的儲存結構)
typedef struct _stackstack_t;
說明:item_len: 儲存每個節點的長度
item_num: 棧中節點的個數
stack_size: 棧中可儲存的節點個數
p: 指向棧空間
a.當節點的個數item_num大於stack_size,那麼必須重新申請空間,將原來的資料拷貝到新的空間。
b.當節點的個數減小到一定的數量時,可以重新申請小的資料空間,釋放原來大的空間。
3.hash表
hash由於其快速的查詢能力而著稱,但是它太浪費記憶體了,所以用得的比較少,僅僅是在函式的呼叫時被使用。因為函式的呼叫是頻繁的,如果從頭查詢函式,那將浪費很多的時間。這裡引入hash也是必要的。
C語言直譯器的實現 儲存結構 一
目錄 1.記憶體池 2.棧 3.hash表 1.記憶體池 在一些小的程式裡,沒什麼必要新增記憶體管理模組在裡面。但是對於比較複雜的 如果需要很多的記憶體操作,那麼加入自己的記憶體管理是有必要的。至少有一些好處 能夠加快記憶體的申請和釋放 能夠輕鬆的查詢記憶體洩露問題 能夠對整個軟體的記憶體消耗做乙個...
C語言直譯器的實現 序 零
在寫cutec文字編輯器的同時,為了使之有指令碼執行能力。特意實現了乙個簡易的c語言直譯器,所謂的直譯器,就是它是解析執行指令碼檔案的,並不產生可執行的目標 它具備了c語言的幾乎全部的語法。隨著時間的推移,我打算把它作為乙個獨立的專案來開發了。在這個過程中,自己也學到了不少的知識,所以也打算跟大家分...
直譯器模式(C 實現)
本部落格旨在個人總結回顧 直譯器模式 給定乙個語言,定義它的文法的一種表示,並定義乙個直譯器,這個直譯器使用該表示來解釋語言中的句子。說明 優點 可擴充套件性比較好,靈活。增加了新的解釋表示式的方式。易於實現簡單文法。缺點 可利用場景比較少。對於複雜的文法比較難維護。直譯器模式會引起類膨脹。直譯器模...