Skip to content

Commit

Permalink
Merge pull request walu#118 from lionsoul2014/master
Browse files Browse the repository at this point in the history
bug fixed for incrrect & operation for EG(active_symbol_table) access
  • Loading branch information
walu authored Oct 20, 2016
2 parents 9edb1af + 2273658 commit 7166370
Show file tree
Hide file tree
Showing 2 changed files with 5 additions and 4 deletions.
2 changes: 1 addition & 1 deletion 2.5.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ zend_hash_find()函数是内核提供的操作HashTable的API之一,如果你
zval **fooval;

if (zend_hash_find(
&EG(active_symbol_table), //这个参数是地址,如果我们操作全局作用域,则需要&EG(symbol_table)
EG(active_symbol_table), //这个参数是地址,如果我们操作全局作用域,则需要&EG(symbol_table)
"foo",
sizeof("foo"),
(void**)&fooval
Expand Down
7 changes: 4 additions & 3 deletions 3.2.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ zval *get_var_and_separate(char *varname, int varname_len TSRMLS_DC)
$a = 1;
$b = &$a;
$b += 5;
</pre>
</pre>
作为一个标准的PHP程序猿,我们都知道$a的值也变成6了。当我们更改$b的值时,内核发现$b是$a的一个用户端引用,也就是所它可以直接改变$b对应的zval的值,而无需再为它生成一个新的不同与$a的zval。因为他知道$a和$b都想得到这次变化!
但是内核是怎么知道这一切的呢?简单的讲,它是通过zval的is_ref__gc成员来获取这些信息的。这个成员只有两个值,就像开关的开与关一样。它的这两个状态代表着它是否是一个用户在PHP语言中定义的引用。在第一条语句($a = 1;)执行完毕后,$a对应的zval的refcount__gc等于1,is_ref__gc等于0;。 当第二条语句执行后($b = &$a;),refcount__gc属性向往常一样增长为2,而且is_ref__gc属性也同时变为了1!
最后,在执行第三条语句的时候,内核再次检查$b的zval以确定是否需要复制出一份新的zval结构来,这次不需要复制,因为我们刚才上面的get_var_and_separate函数其实是个简化版,并且少写了一个条件:
Expand All @@ -111,16 +111,17 @@ if ((*varval)->is_ref || (*varval)->refcount < 2) {
````
这里我们可以看到,$a,$b,$c这三个变量现在共用一个zval结构,有两个属于change-on-write组合($a,$c),有两个属于copy-on-write组合($a,$b),我们的is_ref__gc和refcount__gc该怎样工作,才能正确的处理好这段复杂的关系呢?
The answer is: 不可能!在这种情况下,变量的值必须分离成两份完全独立的存在!$a与$c共用一个zval,$b自己用一个zval,尽管他们拥有同样的值,但是必须至少通过两个zval来实现。见图3.2【在引用时强制复制!】
<p style="text-align:center"><img src="http://www.walu.cc/phpbook/image/03fig02.jpg" />
<p style="text-align:center"><img src="http://www.walu.cc/phpbook/image/03fig02.jpg" /></p>
同样,下面的这段代码同样会在内核中产生歧义,所以需要强制复制!
<p style="text-align:center"><img src="http://www.walu.cc/phpbook/image/03fig03.jpg" />
````php
//上图对应的代码
$a = 1;
$b = &$a;
$c = $a;

````
图3.3:
<p style="text-align:center"><img src="http://www.walu.cc/phpbook/image/03fig03.jpg" /></p>
需要注意的是,在这两种情况下,$b都与原初的zval相关联,因为当复制发生时,内核还不知道第三个变量的名字。


Expand Down

0 comments on commit 7166370

Please sign in to comment.