數據結構逆向分析-Map


數據結構逆向分析-Map

map是一個典型的二叉樹結構,准確的來說是一個平衡二叉樹或者紅黑樹,特點是數據存儲是有序的存儲。

參考侯傑老師的stl源碼剖析,map里面采用的是RB-TREE也就是紅黑樹

 

 

map存儲的數據是以鍵值對的形式來存儲的,Key:Value

 

優勢:查找數據效率高,因為是平衡二叉樹

缺點:插入數據效率低,因為要插入后變成平衡二叉樹。

 

 

 

開始分析:

采用比較簡單的代碼:

#include<map>
using std::map;
using std::pair;

int main()
{
map<int, int> MyMap;
int SizeMap = sizeof(MyMap);
MyMap.insert(pair<int, int>(1, 100));
MyMap.insert(pair<int, int>(2, 300));
MyMap.insert(pair<int, int>(3, 150));
MyMap.insert(pair<int, int>(4, 200));
MyMap.insert(pair<int, int>(5, 170));
MyMap.insert(pair<int, int>(6, 180));
MyMap.insert(pair<int, int>(7, 90));




return 0;
}

 

 

然后畫圖表示一下:這就是初始化一個map的內存圖,從分析stl的經驗上來看MyMap中的第一個指針指向的這個0081e5f8又指回去了好像stl容器都有個這個東西,猜測來講沒啥用。然后這個后面的0081F5F8很有可能是一個指向整個平衡二叉樹的頭,然后第三個000很有可能就是一個size來記錄節點的個數,當然這是我們的猜測,還要看內存來說話。

 

 

執行第一條插入指令:

 MyMap.insert(pair<int, int>(1, 100));

成了這樣:

 

 

再來猜測一下,首先這個MyMap的第一個字段肯定是沒啥用了,然后最后一個字段確實是里面的大小,然后第二個字段指向的內容,很有可能是指向來了根節點,然后節點的內容里面,最后兩個字段是來存放 key->value鍵值對的。有一些字段暫時不知道有啥用,繼續往下弄幾個看看。

 

執行第二條和第三條指令:

 MyMap.insert(pair<int, int>(2, 300));
MyMap.insert(pair<int, int>(3, 150));

首先這里的平衡二叉樹應該是這樣的:

 

 

如果所有箭頭都標出來會比較亂,所以這里只用了一些關鍵的:

 

 

由此可以推出來,這個map第二個字段指向的應該是一個總領作用的結構體,其中第二個字段指向的是平衡二叉樹的根節點,然后第一個和第三個字段是什么意思暫時不知道,最后一個結束字段的0101也不知道,然后數據節點的話,通過對根節點猜測,第一個字段應該指向的是左節點,第三個字段指向的是右節點。

目前的結果是這樣:

 

 

再參考侯傑老師的stl源碼剖析書后:

 

 

可以確定很多東西了:

 

 

根據侯傑老師的定義重新寫代碼分析:

由於目前只有cdcd后面哪兩個字節的內容不知道了,這里我選擇根據官方書重新寫代碼來觀察這個字段的內容:

#include<map>
using std::map;
using std::pair;

int main()
{
map<int, int> MyMap;
int SizeMap = sizeof(MyMap);
MyMap.insert(pair<int, int>(5, 100));
MyMap.insert(pair<int, int>(6, 300));
MyMap.insert(pair<int, int>(8, 150));
MyMap.insert(pair<int, int>(7, 200));
MyMap.insert(pair<int, int>(11, 170));
MyMap.insert(pair<int, int>(10, 180));
MyMap.insert(pair<int, int>(12, 90));
MyMap.insert(pair<int, int>(13, 400));
MyMap.insert(pair<int, int>(15, 400));


return 0;
}

這里畫圖太麻煩,我只畫比較關鍵的內容了:

 

 

可以看到內容只有0和1,我測試是平衡二叉樹的平衡因子,但是不對,如果是平衡因子的畫13為啥是0001,由於這個底層是紅黑樹,所以這里我猜是用來標記紅黑的。

紅黑樹的性質:

規則1:節點是紅色或黑色的;
規則2:根節點是黑色的;
規則3:每個葉子節點都是黑色的空節點(NIL節點);
規則4:每個紅色節點的兩個子節點都是黑色的(從每個葉子到根的所有路徑上不可能有兩個連續的紅色節點);
規則5:從任一節點到其每個葉子節點的所有路徑都包含相同數目的黑色節點;
將紅黑樹的節點默認顏色設置為紅色,是為盡可能減少在插入新節點對紅黑樹造成的影響。

也就是說8肯定是黑色,那么默認是紅色的情況下6,11是紅色,而紅色不能連續,紅色的子節點必須是黑色,則5,7,10,13肯定是黑色,而默認是紅色,且不會影響別的那么12,15也就是紅色。

破案了:情況非常吻合,紅色為0000,黑色為0001。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM