日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費收錄網(wǎng)站服務,提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

C語言幾乎唯一的缺點就是,需要手動管理內(nèi)存。

拋開這點之外,我覺得其他語言都不如C語言[呲牙]

所以,雖然自動內(nèi)存管理比較復雜,但我還是給scf編譯器框架加了靜態(tài)的GC算法

在編程方面,自動內(nèi)存管理一般叫GC算法,是英文GarbageCollection的縮寫。

棧內(nèi)存的管理比較簡單,是由編譯器根據(jù)函數(shù)調(diào)用鏈而自動管理的。

堆內(nèi)存的管理,在C語言里是由程序員手動管理的。

因為程序員管理錯了堆內(nèi)存而導致的BUG,是C語言最常見、也最難搞的BUG。

所以,后來的編程語言都對內(nèi)存管理做了簡化,例如C++的智能指針。

C++的智能指針,是一種半自動的內(nèi)存管理機制:

它把一個堆內(nèi)存的指針放在一個類的成員變量里,利用局部對象離開作用域時的析構(gòu)函數(shù),來完成堆內(nèi)存的釋放

所以C++的效率比其他語言快得多,因為局部對象什么時候離開作用域,是可以在編譯時就確定的,不需要在運行時做額外的處理。

也就是說,C++的智能指針是靜態(tài)的GC算法。

在編譯時就處理好的算法,是靜態(tài)的算法。

在運行時才會處理的算法,是動態(tài)的算法。

動態(tài)的算法依賴于運行時狀態(tài),對程序的速度有較大的影響:

1,因為框架在處理對象內(nèi)存的回收時,用戶程序不得不暫停

2,否則兩邊發(fā)生競爭條件,那就是跟C語言的野指針一樣的BUG。

寫過C語言的都知道,多線程的野指針是非常難查的BUG,因為程序跑飛了不知道會core在哪里,而且BUG也不是必現(xiàn)的

為什么程序員怕有主控軟件的交通工具?

因為程序員知道多線程+競爭條件+野指針==隨機crash+ 事后找不到第一現(xiàn)場[捂臉]

動態(tài)的GC算法,為了避免出現(xiàn)第2種情況,那就只能使用第1種情況。

1,GC算法有必要動態(tài)的嗎?

實際上沒必要,否則C語言怎么手動管理內(nèi)存的。

C語言的free()代碼肯定是在編譯之前就寫好了的!

只要寫對了free()位置,C語言既不會出BUG,也不會內(nèi)存泄漏。

所以,編譯器只要代替程序員添加free(),就可以自動管理內(nèi)存了。


 

free()的添加位置,當然是在變量離開作用域時。

如上圖:

有4個對象變量m0, m1, m2, m3,

main()函數(shù)返回時也是它們離開作用域的時候,所以在main函數(shù)的結(jié)尾自動添加釋放代碼,程序員就不用手動釋放內(nèi)存了。

2,怎么檢測變量什么時候離開作用域?

在編譯器的后端:

1)代碼的每個基本塊都是流程圖上的一個節(jié)點

2)基本塊之間通過跳轉(zhuǎn)聯(lián)系起來,

3)基本塊內(nèi)部的代碼是順序運行的。

所以,釋放內(nèi)存的代碼需要加在兩個基本塊之間。

上述main()函數(shù)的流程圖

上圖是前面的main()函數(shù)的流程圖

創(chuàng)建一個對象分兩步:第一步調(diào)用malloc()申請內(nèi)存,第二步調(diào)用構(gòu)造函數(shù)__init()初始化內(nèi)存。

(為了簡化代碼,我沒有做返回值為NULL的檢查)

在第8個基本塊 m3 = m0 + m1 + m2 之后,m0, m1, m2 就不再使用了,也就是它們3個離開作用域了。

即使在源代碼層面這時m0, m1, m2依然處于main()函數(shù)的作用域內(nèi),但對后端來說它們已經(jīng)離開作用域了,因為之后的基本塊都不再使用它們了。

所以,對m0, m1, m2的釋放代碼,應該加在第8第9號基本塊之間

第9號基本塊會把指針m3->data賦值給dd,這會讓(m3->data)內(nèi)存的引用計數(shù)+1。

對m3的釋放代碼可以放在第9第10之間,之后不會再使用m3了:這會讓m3->data的引用計數(shù)-1。

這時,內(nèi)存數(shù)據(jù)有且只有1個引用計數(shù)(一開始自帶1個),同時有且只有指針dd指向它。

指針dd的釋放在for循環(huán)之后,即第10和11之間:這里的釋放會讓引用計數(shù)減少到0。

在引用計數(shù)為0時,要調(diào)用free()函數(shù),把內(nèi)存還給系統(tǒng)

GC算法的要點有3個:

1)什么時間調(diào)用的malloc(),

2)什么時間有指針的賦值,要把引用計數(shù)+1,

3)什么時間離開作用域,也就是后續(xù)不再使用對象變量,要把引用計數(shù)-1,如果減少之后為0,就調(diào)用free().

3,跨函數(shù)指針分析,

有時候,申請的內(nèi)存并不會在當前函數(shù)內(nèi)釋放,而是返回給更上層的主調(diào)函數(shù)。

這時的GC算法,就需要跨越函數(shù)的調(diào)用鏈,進行指針分析。

mat類的構(gòu)造函數(shù)__init()

前面的mat對象的成員指針m3->data,就是需要跨函數(shù)分析的指針。

它是在構(gòu)造函數(shù)里申請的內(nèi)存,因為是成員變量,所以要在析構(gòu)函數(shù)里釋放。

如果是局部變量,就在當前函數(shù)內(nèi)釋放:因為局部變量的作用域就是當前函數(shù)。

mat類的聲明,成員變量部分

成員變量的有效時間,是伴隨著當前對象的。

局部變量的有效時間,是伴隨著當前函數(shù)的。

成員變量在構(gòu)造函數(shù)返回時依然有效,所以要把它是malloc()申請的這個信息,傳遞到更上層的函數(shù)。

這樣:

1)在main()里才知道它是malloc()申請的,

2)在 dd = m3->data 時才知道給它指向的內(nèi)存引用計數(shù)+1

3)在釋放m3時,析構(gòu)函數(shù)引用計數(shù)-1之后,引用計數(shù)才不為0:內(nèi)存依然是有效的,這時指針dd依然指向它。

否則,dd就是野指針了!

mat類的析構(gòu)函數(shù)__release()

函數(shù)調(diào)用鏈,在語義分析時是很容易確定的。

抽象語法樹AST上的每一個函數(shù)調(diào)用,必然有一個主調(diào)函數(shù)、有一個被調(diào)函數(shù)

主調(diào)和被調(diào),構(gòu)成了整個程序的函數(shù)調(diào)用圖

最頂層的是main()函數(shù),最底層的是malloc()函數(shù)。

以malloc為起點、main為終點,做圖的寬度優(yōu)先搜索,就可以獲取整個調(diào)用鏈。

然后從離malloc最近的函數(shù)開始,一層層的分析就行了。

函數(shù)調(diào)用圖

一定是用圖的寬度優(yōu)先搜索BFS)!

不能用深度優(yōu)先搜索DFS),因為一個上層函數(shù)可能調(diào)用多個下層函數(shù),而這多個下層函數(shù)里都malloc了內(nèi)存。

如上圖:

如果是DFS,分析順序是A->D,這樣D調(diào)用B而申請的內(nèi)存就會被漏過去了。

如果是BFS,分析順序是A->B->C->D->E,這樣任何函數(shù)申請的內(nèi)存如果傳遞給上層,(在分析上層函數(shù)時)都不會被漏過去。

4,遞歸調(diào)用指針分析,

上圖的C()和E()之間的互相調(diào)用構(gòu)成遞歸,表現(xiàn)為函數(shù)調(diào)用圖上的回路

這種情況下,兩個函數(shù)里申請的內(nèi)存互相傳遞,屬于最復雜的一種情況!

在編譯器里的處理方法是:

do {

delivery = check_delivery();

} while (0 == delivery);

do while循環(huán)檢查內(nèi)存的傳遞情況,記錄傳遞的變量和計數(shù),直到不再發(fā)生變化為止。

最后,就是在合適的位置添加free()代碼了:

最后的總是最簡單的,the last is the simplest.

有興趣了解細節(jié)的,可以看我寫的scf編譯器框架的GC算法。

編譯原理(龍書)里沒有這方面的算法,這是我自己想出來的

聽說又像牛頓跟萊布尼茨一樣,跟rust的作者相見略同了是吧[捂臉]

我先起個直白的名字叫static GC.

老外就那樣,有一點點的改進就猛吹[捂臉]

神經(jīng)網(wǎng)絡都能被辛頓吹成deep learning

分享到:
標簽:編譯器
用戶無頭像

網(wǎng)友整理

注冊時間:

網(wǎng)站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨大挑戰(zhàn)2018-06-03

數(shù)獨一種數(shù)學游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數(shù)有氧達人2018-06-03

記錄運動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定