PHP Kernel Explorer variable (2)-Understanding Reference _php Tutorial

Source: Internet
Author: User
Tags derick

PHP Kernel Explorer variables (2)-Understanding references


The main content of this article:

Introduction symbol table and Zval reference principle back to the original question

First, Introduction

A long time ago wrote an article about quoting, at that time wrote a few hasty, many principles are not clear. In a recent report on Derick Rethans (Home:http://derickrethans.nl/github:https://github.com/derickr), I found an article explaining the PHP reference mechanism, This is the PDF. In this paper, from the angle of zval and symbol table explained the principle of reference count, reference, reference return, global parameters and so on, voluminous, illustrated, very wonderful, it is recommended that children have time to read the original, I believe there will be a lot of harvest.

Don't say much nonsense, go on to the point today.

We know that many languages provide a mechanism for referencing, which allows us to use different names (or symbols) to access the same content. The reference definition in the PHP manual is: "Referencing in PHP means accessing the same variable content in a different name." This is not like the C pointer, instead, the reference is the symbol table alias. "In other words, the reference implements some form of" binding. " For example, the kind of interview questions that we often encounter are examples of references:

$a = Array (1,2,3,4), foreach ($a as & $v) {     $v *= $v;} foreach ($a as $v) {     echo $v;}

Cast out the output of the problem, we today follow the footsteps of Derick Rethans predecessors, step by step to uncover the mysterious veil of reference.

Second, symbol table and Zval

Before we begin the principle of reference, it is necessary to make a simple explanation of the recurring terms in the text, the most important of which is the following: 1. symbol table 2.zval.

1. Symbol table

Computer language is a tool for people to communicate with machines, but unfortunately, the high-level languages on which we live and pride cannot be executed directly on computers, because computers can only understand some form of machine language. This means that high-level languages must be compiled (or interpreted) to be understood and executed by the computer. In the meantime, through lexical analysis, grammar analysis, semantic analysis, intermediate code generation and optimization of a lot of complex processes, and in these processes, the compiler may be used repeatedly in the source program identifiers and other information (such as variable type check, semantic analysis phase of the semantic check), This information is stored in a different symbol table. The symbol table holds the name and attribute information for identifiers in the source program, which may include: type, storage type, scope, storage allocation information, and other additional information. In order to efficiently insert and query symbol table entries, many compiler symbol tables are implemented using Hashtable. We can simply understand that the symbol table is a hashtable or map that holds the symbol name and the various attributes of the symbol. For example, for a program:

$str = ' This is a test '; function foo ($a, $b) {    $tmp = n;    return $tmp + $a + $b;}  function to () {}

A possible symbol table (not an actual symbol table) is a structure similar to this:

We don't pay attention to the specific structure of the symbol table, just know that each function, class, namespace, and so on have their own separate symbol table (separate from the global symbol table). Speaking of this, suddenly think of one thing, when you first use PHP programming, when reading the Manual of the Extract () function, for "Import variables from the array into the current symbol table" the meaning of the sentence is not a solution, but also for the predecessors said " It is not recommended to use Extract ($_post) and extract ($_get) to extract variables "of the recommendations are extremely distressed. In fact, the abuse of extract will not only have serious security problems, but also pollute the current symbol table (active symbol tables).

So what is active symbol table?

We know that the execution of PHP code is almost always starting from the global scope, sequentially scanning, sequential execution. If a function call is encountered, it is executed inside the function and returned to the calling program to continue execution after the function has finished executing. This means that there must be some mechanism for distinguishing between the symbol tables to be used at different stages, or it will cause confusion in compilation and execution. The active symbol table is the symbol tables used to flag the current activity (at this point there should be at least the global symbol table and active active symbol table, which, in general, active symbol Table refers to the global symbol table). The symbol table is not built in the first place, but is constantly being added and updated as the compilation program scans. When entering a function call, Zend (the language interpreter engine for PHP) creates the symbol table for the function and points the active symbol table to the symbol tables. In other words, the symbol table used at any one time should be the current active symbol table.

The above is the entire contents of the symbol table, we simply pull away from the key content:

The symbol table records the Name-attribute pairs of symbols in the program, which are critical for compiling and executing. The symbol table is like a map or Hashtable symbol table is not built from the start, but the process of constantly adding and updating. The active symbol table is a pointer to the currently active symbol table.

More information can be viewed:

1. http://www.scs.stanford.edu/11wi-cs140/pintos/specs/sysv-abi-update.html/ch4.symtab.html

2. Http://arantxa.ii.uam.es/~modonnel/Compilers/04_SymbolTablesI.pdf

2. Zval

In the previous blog (PHP kernel Explorer variable (1) zval), we have some understanding of the structure and fundamentals of Zval. Children's shoes that zval don't know can be seen first. To facilitate reading, we re-post the structure of the Zval:

struct _zval_struct {    zvalue_value value;       /* Value */    zend_uint refcount__gc;   /* Variable ref count */    Zend_uchar type;         /* Active type */    Zend_uchar is_ref__gc;    /* If it is a ref variable */};typedef struct _zval_struct zval;

Iii. references

1. Reference counting

As noted in the previous section, Zval is the real container for PHP variables at the bottom, and in order to save space, not every variable has its own Zval container, such as for assignment (Assign-by-value) operations: $a = $b (assuming $b, $a is not a reference variable), Zend does not $b variable opens up new space, but instead points A and B symbols in the symbol table to the same zval. An zval detach operation is performed only if one of the variables changes. This is called the Cow (copy-on-write) mechanism, which can save memory and improve efficiency to some extent.

In order to implement the above mechanism, it is necessary to mark the reference state of Zval, zval structure, REFCOUNT__GC is used for counting, this value records how many variables point to the Zval, in the above assignment operation, $a = $b, will increase the original $ The RefCount value of the Zval B. In this regard, the last (PHP kernel exploration variable (1) zval) has been explained in detail, here no longer repeat.

2. Function parameters

The global symbol table is almost always present during the execution of the script, but in addition to the global symbol table, it will actually generate other symbol tables: for example, during a function call, Zend creates the internal symbol table of the function, The information used to hold the variables inside the function, and after the function call is finished, the symbol table is deleted. We will then take a simple function call as an example to introduce the change in the state of variables and zval in the process of parameter transfer, and the test script we use is:

function Do_zval_test ($s) {    $s = "change";    return $s;} $a = "before"; $b = Do_zval_test ($a);

Let's step through the analysis:

(1). $a = "before";

This will open a new Zval (refcount=1,is_ref=0) for the $ A variable as follows:

  

(2). function call Do_zval_test ($a)

Because of the invocation of the function, Zend creates a separate symbol table for the Do_zval_test function, which contains the symbol s inside the function, and since $s is actually a function's formal parameter, it does not create a new zval for $s, but a $ a zval. At this point, the zval that the $a points to RefCount should be 3 ($ A, $s, and the function call stack, respectively):

A: (refcount=3, is_ref=0) = ' before Func '

As shown in the following:

  

(3). function internal Execution $s = "change"

Because the value of $s has changed, the zval separation is performed and a new zval is generated for the s dedicated copy:

(4). function returns return $s; $b = Do_zval_test ($a).

$b share Zval (temporarily) with $s, prepare to destroy the symbol table in the function:

(5). Destroy the symbol table in the function and return to the Global environment: <喎?"http: www.bkjia.com="" kf="" ware="" vc="" "="" target="_blank" class="keylink"> vc3ryb25npjwvcd4kpha+idxpbwcgc3jjpq== "http://www.2cto.com/uploadfile/Collfiles/ 20141129/20141129083533169.jpg "alt=" \ ">

Here, incidentally, when you use a function such as debug_zval_dump () to view Zval's RefCount, the RefCount value of the zval itself is added to 1, so the actual refcount value should be the printed refcount minus 1, as shown below:

$SRC = "string";d ebug_zval_dump ($SRC);

The result is:

String (6) "String" RefCount (2)

3. References

Ditto, we still directly on the code, and then step by step analysis (This example is relatively simple, in order to integrity, we still a little analysis):

$a = "simple test"; $b = &a; $c = &a; $b = 42;unset ($c); unset ($b);

The corresponding relationship between the variable and the Zval is as follows: (This shows that the function of unset is simply to remove the variable from the symbol table and reduce the refcount value of the corresponding Zval)

A notable last step, after unset ($b), Zval's is_ref value becomes 0.

What if it's a script that mixes references (assign-by-reference) and normal assignments (assign-by-value)?

Our test script:

(1). Reference assignment before normal assignment

$a = "src"; $b = $a; $c = & $b;

For the specific process, see:

(2). General assignment after the assignment of the first value

$a = "src"; $b = & $a; $c = $a;

See the specific process:

4. Passing references

Similarly, parameters passed to a function can be passed as a reference, so that the value of the variable can be modified inside the function. As an example, we still use the script in 2 (function pass), except that the argument changes to a reference form:

Function do_zval_test (& $s) {    $s = "after";    return $s;} $a = "before"; $b = Do_zval_test ($a);

This is basically the same as the procedure of the above function, and the difference is that the value of $ A is changed by the passing of the reference. Also, after the function call ends $a is_ref reverts to 0:

As you can see, the difference between a reference pass and a normal value pass is that:

(1) The 3rd step $s = "change"; When you do not create a new zval for $s, but with $ A to point to the same zval, this zval is_ref=1.

(2) or the 3rd step. $s = "change"; after execution, the value of $ A is changed indirectly because of Zval's is_ref=1.

5. Reference returns

Another feature that PHP supports is the reference return. We know that in C + +, when a function returns a value, it actually generates a copy of the value, and when the reference returns, it does not generate a copy, and the way the reference returns can save memory and improve efficiency to some extent. In PHP, this is not exactly the case. So what exactly is a reference to return? This is what the PHP manual says: " reference returns are used when you want to use a function to find out which variable the reference should be bound to," isn't confused, completely unintelligible? In fact, the English manual is described in this way "returning by reference are useful when you want to usea function to find to which variable a reference should be bound". Extracting the backbone and key points in the article, we can get this information:

(1). The reference return is to bind the reference to a variable.

(2). This variable is not deterministic, but is obtained through a function (we can use a normal reference).

This also illustrates the limitations of the reference return: The function must return a variable, not an expression, and a question similar to the following will appear:

PHP Notice: Only  variable references should is returned by reference in XXX (see the note in the PHP manual).

So, how does a reference work when it returns? For example, for the following example:

function &find_node ($key,& $tree) {    $item = & $tree [$key];    return $item;}  $tree = Array (1=> ' one ',2=> ',3=> ' three '); $node =& Find_node (3, $tree); $node = ' new ';

What did Zend do? We take a step-by-step look.

(1). $tree = Array (1=> ' one ',2=> ', ',3=> ' three ')

As before, this adds the tree symbol to the global symbol table and generates the zval of the variable. At the same time, each element of an array $tree generates a corresponding zval:

Tree: (Refcount=1, Is_ref=0) =array (    1 = (refcount=1, is_ref=0) = ' One ',    2 = (refcount=1, is_ref=0) = ' Both ',    3 = (refcount=1, is_ref=0) = ' three ')

As shown in the following:

(2). Find_node (3,& $tree)

Because of a function call, Zend enters the inside of the function, creates the inner symbol table of the function, and since the passed argument is a reference parameter, the is_ref of Zval is flagged as 1, and the value of RefCount is increased to 3 (the global tree, respectively, Internal tree and function stack):

(3) $item = & $tree [$key];

Because item is a reference to $tree[$key] (in this case, the $key is 3), updating $tree[$key] points to zval Is_ref and RefCount values:

(4) Return $item and perform a reference binding:


(5) The function returns, destroying the local symbol table.

The is_ref of the tree corresponding to the zval restored 0,refcount=1, and $tree [3] was bound to the $node variable, and any change to that variable would indirectly change $tree[3]:


(6) Changing the value of the $node will be reflected to the $tree node, $node = "new":

Note: In order to return using a reference, the & symbol must be explicitly used where the function definition and function call are applied.

6. Global keyword

PHP allows us to use the Global keyword within the function to refer to the Globals (the local variables of the function are referenced without adding the global keyword), for example:

$var = "Outside"; function inside () {    $var = "Inside";    echo $var;    Global $var;    echo $var;} Inside ();

Output is insideoutside

We only know that the Global keyword establishes a binding of local variables and global variables, so what is the specific mechanism?

Use the following script tests:

$var = "one";      function Update_var ($value) {         global $var;         Unset ($var);         Global $var;         $var = $value;} Update_var (' four '); Echo $var;

The specific analysis process is:

(1). $var = ' one ';

As before, this adds the Var symbol to the global symbol table and creates the corresponding Zval:

(2). Update_var ("four")

Because a string instead of a variable is passed directly, a zval is created, the is_ref=0,ref_count=2 of the Zval (respectively, the parameters $value and the stack of functions), as follows:

(3) Global $var

Global $var This sentence, in fact, will do two things:

(1). Insert the local var symbol in the symbol table inside the function

(2). Establish a reference between the local $var and the global variable $var.

(4) unset ($var);

It is important to note that unset simply removes the var symbol from the inner symbol table of the function , rather than deleting the global. At the same time, update the RefCount value of the original zval and the IS_REF reference flag (reference to unbind):

(5). Global $var

With 3, the local $var is again established with the global $var reference:

(6) $var = $value;

Change the value of the zval corresponding to the $var, and the value of the global $var will change as the reference exists:

(7) function return, destroy the local symbol table (back to the original starting point, but, everything has been very different):


Thus, we can summarize the process and features of the Global keyword:

The function declares the global, generates a local variable inside the function, and with the global variableEstablish references。 Any change to the global variable in the function will indirectly change the value of the globals. The function unset Local variables does not affect global, but only the binding to the Globals.

Iv. back to the original question

Now, we have a basic understanding of references. Let's go back to the original question:

$a = array, foreach ($a as & $v) {     $v *= $v;} foreach ($a as $v) {     echo $v;}

What is going on here?

(1). $a = Array (All-in-all);

This generates a $ A zval in the global symbol table and generates a corresponding zval for each element:

(2). foreach ($a as & $v) {$v *= $v;}

Because this is a reference binding, it is equivalent to an element in an array:

$v = & $a [0]; $v = & $a [1]; $v = & $a [2];

The execution process is as follows:

We found that after this foreach execution,$v = & $a [2].

(3) Second foreach Loop

foreach ($a as $v) {     echo $v;}

This time because it is the normal assign-by-value of the assignment form, so, similar to the execution:

$v = $a [0]; $v = $a [1]; $v = $a [2];

Don't forget that $v is now a reference to $a[2], so the process of assigning the value indirectly changes the value of $a[2].

The process is as follows:

Therefore, the output should be 144.

Attached: The debugging method of Zval in this article.

If you want to see Zval changes in a process, the best way is to add debugging code before and after the procedure. For example

$a = 123;xdebug_debug_zval (' a '); $b =& $a; Xdebug_debug_zval (' a ');

With drawing, you can get an intuitive zval update process.

Reference documents:

Http://en.wikipedia.org/wiki/Symbol_tablehttp://arantxa.ii.uam.es/~modonnel/Compilers/04_SymbolTablesI.pdfhttp ://web.cs.wpi.edu/~kal/courses/cs4533/module5/myst.htmlhttp://www.cs.dartmouth.edu/~mckeeman/cs48/mxcom/doc/ typeinference.pdfhttp://www.cs.cornell.edu/courses/cs412/2008sp/lectures/lec12.pdfhttp://php.net/manual/zh/ Language.references.return.phphttp://stackoverflow.com/questions/10057671/how-foreach-actually-works

Due to the haste of writing, it is inevitable that there will be errors in the text, and we welcome the discussion.

http://www.bkjia.com/PHPjc/925223.html www.bkjia.com true http://www.bkjia.com/PHPjc/925223.html techarticle PHP Kernel Explorer variables (2)-Understand the main content of this article: Introduction symbol table and Zval reference principle back to the original question one, the introduction long ago wrote an article about quoting, ...

  • Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.