皆知PHP的数组是由HashTable和双链表实现的,为了方便大家查看数组的数据结构,开发一个遍历PHP的数组生成Dot描述的PHP插件,生成dot描述以后可以通过一些渲染工具生成图像,本例用的是 Graphviz。
扩展的实现很简单,PHP数组源码是由下面的两种结构体实现的,扩展就是将这两种结构体和各个结构体的关系遍历一遍,生成对应的Dot描述即可。
扩展里边函数说明
---------------------------------------------------------------------------------------------
string dotarray( array $input [, int $flag] )
生成数组数据结构的dot描述
参数
input 需要操作的数组
flag 查看那些数据结构,是扩展提供的3个常量或操作,分别是
DOTARAAY_HASH_TABLE 表示显示HashTable结构
DOTARRAY_DOUBLE_LIST 显示数组的双链表结构
DOTARRAY_CURRENT_POSITION 显示数组现在的内部指针的位置
返回值
成功返回dot描述字符串,错误(非数组等情况)返回false
---------------------------------------------------------------------------------------------
显示双链表结构例子
得到的dot描述:
通过graphviz渲染得到下面的图片
需要解释一下,红色实线为结构中双链表的next指针,红色点线为上一个元素指针。同时提供了DOTARRAY_CURRENT_POSITION标志,出现绿线指向数组内部指针指向key为1的元素(第一个元素key为0)
显示HashTable结构例子
生成的结构图片如下:
hash冲突的例子
具体可以参考 PHP hash碰撞拒绝服务漏洞原理 http://www.laruence.com/2011/12/29/2412.html ,简单介绍即是:Hash表因为”冲突”(碰撞)而退化成链表,如果数据量足够大, 使得php在计算, 查找, 插入的时候, 造成大量的CPU占用, 从而实现拒绝服务攻击。下面是简单的碰撞生成代码:
<
这次将hashtable和双线表同时展示出来,传递的flag为DOTARRAY_DOUBLE_LIST|DOTARAAY_HASH_TABLE,同时展示双链表和HashTable
关于 dot语言 传送门:http://zh.wikipedia.org/wiki/DOT%E8%AF%AD%E8%A8%80
扩展的实现很简单,PHP数组源码是由下面的两种结构体实现的,扩展就是将这两种结构体和各个结构体的关系遍历一遍,生成对应的Dot描述即可。
- 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
---------------------------------------------------------------------------------------------
显示双链表结构例子
- <?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描述:
- 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渲染得到下面的图片
![点击查看原始大小图片](https://i-blog.csdnimg.cn/blog_migrate/895b9e580755ca9c585b67bb6fe0c703.png)
需要解释一下,红色实线为结构中双链表的next指针,红色点线为上一个元素指针。同时提供了DOTARRAY_CURRENT_POSITION标志,出现绿线指向数组内部指针指向key为1的元素(第一个元素key为0)
显示HashTable结构例子
- <?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;
生成的结构图片如下:
![点击查看原始大小图片](https://i-blog.csdnimg.cn/blog_migrate/ff9f5fa32cb14f0eac3adce2ef046e57.png)
hash冲突的例子
具体可以参考 PHP hash碰撞拒绝服务漏洞原理 http://www.laruence.com/2011/12/29/2412.html ,简单介绍即是:Hash表因为”冲突”(碰撞)而退化成链表,如果数据量足够大, 使得php在计算, 查找, 插入的时候, 造成大量的CPU占用, 从而实现拒绝服务攻击。下面是简单的碰撞生成代码:
<
- ?php
- /*会生出pow(2,$n)个数字*/
- $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
![点击查看原始大小图片](https://i-blog.csdnimg.cn/blog_migrate/41b9a39215c0374c82f68bad412ed2c9.png)
关于 dot语言 传送门:http://zh.wikipedia.org/wiki/DOT%E8%AF%AD%E8%A8%80
关于 dot渲染工具Graphviz 传送门:http://www.graphviz.org/
扩展源码:https://github.com/Himer/dotarray