比方说我声明一个数组:
$data = array( 'foo' => 'bar' );
现在我将添加一个对自身的引用作为一个新元素:
$data['baz'] = &$data;
倾倒内容$data
将导致:
Array
(
[foo] => bar
[baz] => Array
(
[foo] => bar
[baz] => Array
*RECURSION*
)
)
现在,我可以转储内容$data['baz']['baz']['baz']['baz']['baz']['baz']['baz']['baz']['baz']
并且结果与上述内容完全相同,因为数组有一个指向自身的指针作为元素。
我想知道的是,如果php将数组作为一个单一的数据集处理,并且指针与我在使用时指向的指针完全相同,$data
或者它完成了一些完全不同的操作。
此外,PHP可能会在尝试返回内容时耗尽内存$data{['baz']*n}
?
发布于 2018-03-21 13:41:15
在PHP内部,所有内容都存储在称为ZVAL的变体容器中。由ZVAL表示,每个键和每个值都是ZVAL等。$data$data
所以在初始分配后,PHP创建了三个ZVAL:
/-------------------\ /-------------------\
| ZVAL #1 | /==>| ZVAL #2 |
| type: array | | | type: string |
| data: [ | | | data: "foo" |
| { | | \-------------------/
| key: =======/ /-------------------\
| val: ================================>| ZVAL #3 |
| } | | type: string |
| ] | | data: "bar" |
\-------------------/ \-------------------/
你可以看到这样的事实"foo"
和"bar"
被用作数组键/值对是不可能通过看他们的变量容器,以确定:你要知道,他们正在由数组引用。
分配之后$data['baz'] = &$data
,会发生什么情况?你现在有一个循环引用:位于ZVAL#1内的某个位置有一个指向ZVAL#1的指针:
/-------------------\ /-------------------\
| ZVAL #1 | /==>| ZVAL #2 |
/=>| type: array | | | type: string |
| | data: [ | | | data: "foo" |
| | { | | \-------------------/
| | key: =======/ /-------------------\
| | val: ================================>| ZVAL #3 |
| | }, | | type: string |
| | { | | data: "bar" |
| | key: =========================\ \-------------------/
| | val: =========\ |
| | } | | | /-------------------\
| | ] | | \======>| ZVAL #4 |
| \-------------------/ | | type: string |
| | | data: "baz" |
\===========================/ \-------------------/
那么PHP如何解决$data['baz']['baz']
?它知道这$data
是由ZVAL#1表示的,它看到你正试图用数组语法对它进行索引。它看着ZVAL,看到它是一个数组,找到具有该键的项目"baz"
并获取表示该项目的ZVAL。你知道什么?这再次是ZVAL#1。这就结束了决议$data['baz']
。
在下一步中,它看到你正在尝试将$data['baz']
数组索引。它知道这$data['baz']
是由ZVAL#1表示的,所以同样的事情最终会再次发生,等等。
你将注意到上述过程不涉及存储任何中间结果(第一步和第二步完全独立),这意味着在尝试解析数组访问时,PHP虚拟机不会遇到任何资源限制。
https://stackoverflow.com/questions/-100004284
复制相似问题