STL原始碼剖析中,為什麼空間配置器的union obj最後要跟乙個char陣列?

時間 2021-06-01 23:58:57

1樓:指北

這個union殺了我很多時間,在這留個記錄說不定以後能幫到別人結合《stl原始碼剖析》p65-p67來看:

這東西沒有實際用處,或者說它不必要

要達到用16個鍊錶串起記憶體的效果,用struct node;就夠了因為一旦記憶體塊返回給客戶端,next就沒用了。直接對這塊記憶體覆寫使用即可

猜測寫成這種union的寫法是強調值和鏈可以相互覆蓋這一事實吧,否則單單乙個指標,很難讓人意識到它指向的記憶體會發揮不同的作用瞎猜的

2樓:Joker

由於free_list_link長度較大,union obj的長度為它的整數倍,client_data[1]只佔了其頭部的乙個位元組。因此client_data首位址指向的也就是整個union obj的首位址,亦即實際區塊的位址。

簡單測試下:

#include

#include

union obj{

union obj * free_list_link;

char client_data[1]; /* The client sees this.*/

int main(){

obj * block = (obj *) malloc(128);

printf("%x\n", block);

printf("%x\n", block->client_data);

return 0;

結果為:

1c9c010

1c9c010

這裡client_data其實是作為一種指標型別轉換,為了方便使用。一般記憶體buffer我們都是使用char*指標,如果要使用obj的位址,還得加上 (char *)myBlock 進行強制型別轉換。反之直接使用myBlock->client_data即可,方便多了。

copy於:STL空間配置器的union obj

3樓:弓長禾口王

這是sgi stl中的問題。首先,要弄清楚使用的場景,STL在第二級配置器中的記憶體池中用到自由鍊錶。用上述union結構,可以做到僅用乙個指標的大小來存放兩個資訊:

一是自由鍊錶的下乙個節點;二是自由鍊錶當前節點指向的實際記憶體空間。

client_data可以理解成乙個常量指標,當最初賦值的時候,client_data指向實際記憶體空間,然後再給free_list_link賦值,此時注意由於union的特性,只會修改client_data[0]的大小,即陣列中儲存的值,client_data還是指向實際記憶體空間。換句話說,陣列指向實際記憶體空間,資料的值為多少不影響。

手機碼字有點不方便,各位將就點看。

4樓:

請問題主解決了這個問題了嗎? 我現在也很困惑.

在使用分配給obj的記憶體的時候, 是直接把obj指標cast成相應的型別的, 根本就不需要用到client_data.

我試過把client_data注釋掉測試過通過了, 似乎並沒有什麼問題, 實在不明白這個成員是幹嘛的.

既然只有乙個成員, 用struct是不是更好些?

似乎Nibnat的答案是正解?雖然沒用到,但是可以用client_data避免顯式型別轉換,這樣的話為什麼不用char*而用char

5樓:

當使用者沒有申請記憶體的時候,作為鍊錶指標存在指向下乙個obj,這個時候是不需要記憶體中的資料的,當使用者申請了記憶體之後,這塊記憶體被分配給使用者,client_data用來存資料,此時鍊錶指標就沒用了,也就是說這兩個在乙個時刻只有乙個被使用所有用union來存很適合是哇~~節省記憶體

6樓:gyafdxis

union還是蠻有意思的。

太巧妙,

union object有兩個成員都是pointer.

char client_data[0],object* next

不同時時間用的不一樣,

而union的結構在記憶體中的特殊結構正好滿足,節省了空間。

分配記憶體:

在要給你的記憶體池分配記憶體的時候,

他是從自由區鍊錶取的,自由區鍊錶在客端未使用以前,是用的object*但是分配給客端之後就強制轉換為char*,返回void*,

當然我估計你還會問那如果要釋放那塊記憶體呢?

釋放記憶體:

你分配完之後freelist相應的儲存的自由區鍊錶可用區的首位址就會下移,

釋放的時候是把你釋放的那塊,放在對應freelist指向的那塊自由鍊錶可用區的最前面,其實這裡很簡單,就相當於給鍊錶插個頭節點,,不過這裡要把你的void*強制轉換成object*因為現在不在客端,你要把它和自由區鍊錶的可用區,串成一串,所以這裡必須轉換而且這是union用的是object* 。

最後還有就是不是沒用到,他不會這樣用mem->client_data;

而是這裡(char*)result。

這裡就用了client_data,union中原來是object*,現在成了char*;

另外client_data也只有返回客端才有用。

如果題主要深刻理解這裡,先不要糾結這裡。

往後看,refill()和chunk_alloc()相應題主肯定就明白了。

早上剛醒看到這個,

趕緊答一下。

如果題主要詳細解說sgi stl的記憶體池可以看看我的部落格。

為什麼 React 原始碼不用 TypeScript 來寫?

楊健 語言上來講flow不比typescript差太多吧,sound方面明顯強於ts,最差的就是生態了,但是我乙個內部實現幾乎不依賴啥第三方庫,生態影響微乎其微 賀師俊 先看時間線。TypeScript是2012年10月發布的,2014年10月發的1.1 Flow是2014年11月發布的。React...

為什麼要選擇溯源程式碼燕窩?

weijin 貼有溯源程式碼的燕窩,代表燕窩通過了出口國獸醫檢驗 衛生部檢驗 海關進口檢驗檢疫等多重檢驗檢疫。而過 安檢 的必須滿足 亞硝酸鹽含量低於標準 重金屬 二氧化硫0檢出 非產自禽流感疫情產區等,從而保證了食用安全。 小明停下 從來不認為溯源程式碼燕窩就一定是好燕窩,你看溯源程式碼燕窩的產品...

為什麼unreal虛幻引擎原始碼編譯如此慢,有方法改進嗎?

pixel玩家 改一點點code是不需要編譯整個的,會只編譯那部分修改相關聯的。最好是要有乙個固態硬碟。如果沒有那就會很痛苦。 吳俊璋 有條件的用incredibuild 不想買的可以考慮用SNDBS 和incredibuild比稍微慢一點但是免費如果只是個人的電腦就沒什麼好辦法了 有條件的可以上I...