皆知PHP的數組是由HashTable和雙連結清單實作的,為了友善大家檢視數組的資料結構,開發一個周遊PHP的數組生成Dot描述的PHP插件,生成dot描述以後可以通過一些渲染工具生成圖像,本例用的是 Graphviz。
擴充的實作很簡單,PHP數組源碼是由下面的兩種結構體實作的,擴充就是将這兩種結構體和各個結構體的關系周遊一遍,生成對應的Dot描述即可。
Java代碼
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5ichR3cf52bjl2LcNXZnFWbp9CXt92YuUWelRXauMWas9GaldmbhJ3bvw1LcpDc0RHaiojIsJye.png)
- typedef struct bucket {
- ulong h;
- uint nKeyLength;
- void * pData;
- void * pDataPtr;
- struct bucket * pListNext;
- struct bucket * pListLast;
- struct bucket *pNext ;
- struct bucket * pLast;
- const char *arKey ;
- } Bucket;
- typedef struct _hashtable {
- uint nTableSize;
- uint nTableMask;
- uint nNumOfElements;
- ulong nNextFreeElement;
- Bucket *pInternalPointer;
- Bucket *pListHead;
- Bucket *pListTail;
- Bucket **arBuckets;
- dtor_func_t pDestructor;
- zend_bool persistent;
- unsigned char nApplyCount ;
- zend_bool bApplyProtection;
- } HashTable;
擴充裡邊函數說明
---------------------------------------------------------------------------------------------
string dotarray( array $input [, int $flag] )
生成數組資料結構的dot描述
參數
input 需要操作的數組
flag 檢視那些資料結構,是擴充提供的3個常量或操作,分别是
DOTARAAY_HASH_TABLE 表示顯示HashTable結構
DOTARRAY_DOUBLE_LIST 顯示數組的雙連結清單結構
DOTARRAY_CURRENT_POSITION 顯示數組現在的内部指針的位置
傳回值
成功傳回dot描述字元串,錯誤(非數組等情況)傳回false
---------------------------------------------------------------------------------------------
顯示雙連結清單結構例子
Java代碼
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5ichR3cf52bjl2LcNXZnFWbp9CXt92YuUWelRXauMWas9GaldmbhJ3bvw1LcpDc0RHaiojIsJye.png)
- <?php
- $items = array(1,2,8=>'lalala',16=>'hahaha','name'=>'shiki',30=>'wooooo...');
- next($items);
- $result = dotarray($items,DOTARRAY_DOUBLE_LIST|DOTARRAY_CURRENT_POSITION);
- echo $result;
得到的dot描述:
Java代碼
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5ichR3cf52bjl2LcNXZnFWbp9CXt92YuUWelRXauMWas9GaldmbhJ3bvw1LcpDc0RHaiojIsJye.png)
- digraph html {label = "Structure of array";
- node[shape = record];
- ===========部分内容省略============
- edge [color=black];
- edge [color=green];
- sk_array:f5:s -> sk_item_1:f0;
- edge [color=black];
- }
通過graphviz渲染得到下面的圖檔
需要解釋一下,紅色實線為結構中雙連結清單的next指針,紅色點線為上一個元素指針。同時提供了DOTARRAY_CURRENT_POSITION标志,出現綠線指向數組内部指針指向key為1的元素(第一個元素key為0)
顯示HashTable結構例子
Java代碼
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5ichR3cf52bjl2LcNXZnFWbp9CXt92YuUWelRXauMWas9GaldmbhJ3bvw1LcpDc0RHaiojIsJye.png)
- <?php
- $items = array(1,2,8=>'lalala',16=>'hahaha','name'=>'shiki',30=>'wooooo...');
- next($items);
- next($items);
- $result = dotarray($items,DOTARAAY_HASH_TABLE|DOTARRAY_CURRENT_POSITION);
- echo $result;
生成的結構圖檔如下:
hash沖突的例子
具體可以參考 PHP hash碰撞拒絕服務漏洞原理 http://www.laruence.com/2011/12/29/2412.html ,簡單介紹即是:Hash表因為”沖突”(碰撞)而退化成連結清單,如果資料量足夠大, 使得php在計算, 查找, 插入的時候, 造成大量的CPU占用, 進而實作拒絕服務攻擊。下面是簡單的碰撞生成代碼:
< Java代碼
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5ichR3cf52bjl2LcNXZnFWbp9CXt92YuUWelRXauMWas9GaldmbhJ3bvw1LcpDc0RHaiojIsJye.png)
- ?php
- $n= 3;
- $capacity = pow(2,$n);
- $array =array();
- for($i=0;$i<$capacity;$i++){
- $key = $i<<$n;
- $array[$key] =1;
- }
- $str = dotarray($array,DOTARRAY_DOUBLE_LIST|DOTARAAY_HASH_TABLE);
- echo $str,PHP_EOL;
這次将hashtable和雙線表同時展示出來,傳遞的flag為DOTARRAY_DOUBLE_LIST|DOTARAAY_HASH_TABLE,同時展示雙連結清單和HashTable
關于 dot語言 傳送門:http://zh.wikipedia.org/wiki/DOT%E8%AF%AD%E8%A8%80
關于 dot渲染工具Graphviz 傳送門:http://www.graphviz.org/
擴充源碼:https://github.com/Himer/dotarray