Re: [SMARTY-DEV] Re: [SMARTY] Re:[SMARTY-DEV]$smarty.session.object doesn't work in 2.5.0

From: Date: Tue, 15 Apr 2003 19:22:59 +0000
Subject: Re: [SMARTY-DEV] Re: [SMARTY] Re:[SMARTY-DEV]$smarty.session.object doesn't work in 2.5.0
References: 1 2 3 4 5 6  Groups: php.smarty.dev 
Request: Send a blank email to php-smarty-dev+get-1165@lists.php.net to get a copy of this message
> Right, but Smarty's method of variable assignement always makes a copy > regardless of the data type. As far as I can see that, Smarty does $this->_tpl_vars[$tpl_var] = $value; This creates _definitely_ a reference to $value, as long as $value is not altered. Actually, it is not possible to force the copying of a variable. Always creating references as long as the assigned variables are not altered is a feature which has been introduced with PHP4 in order to avoid unnecessary overhead. Read http://www.zend.com/zend/art/ref-count.php, especially on from paragraph "What is variable counting". You may also look this up in the PHP source, 4.3.1, zend_execute.c, function zend_assign_to_variable, lines 413-487 (explanation follows below): if (PZVAL_IS_REF(variable_ptr)) { if (variable_ptr!=value) { short refcount=variable_ptr->refcount; zval garbage; if (type!=IS_TMP_VAR) { value->refcount++; } garbage = *variable_ptr; *variable_ptr = *value; variable_ptr->refcount = refcount; variable_ptr->is_ref = 1; if (type!=IS_TMP_VAR) { zendi_zval_copy_ctor(*variable_ptr); value->refcount--; } zendi_zval_dtor(garbage); } } else { variable_ptr->refcount--; if (variable_ptr->refcount==0) { switch (type) { case IS_VAR: /* break missing intentionally */ case IS_CONST: if (variable_ptr==value) { variable_ptr->refcount++; } else if (PZVAL_IS_REF(value)) { zval tmp; tmp = *value; zval_copy_ctor(&tmp); tmp.refcount=1; zendi_zval_dtor(*variable_ptr); *variable_ptr = tmp; } else { value->refcount++; zendi_zval_dtor(*variable_ptr); safe_free_zval_ptr(variable_ptr); *variable_ptr_ptr = value; } break; case IS_TMP_VAR: zendi_zval_dtor(*variable_ptr); value->refcount=1; *variable_ptr = *value; break; EMPTY_SWITCH_DEFAULT_CASE() } } else { /* we need to split */ switch (type) { case IS_VAR: /* break missing intentionally */ case IS_CONST: if (PZVAL_IS_REF(value) && value->refcount > 0) { ALLOC_ZVAL(variable_ptr); *variable_ptr_ptr = variable_ptr; *variable_ptr = *value; zval_copy_ctor(variable_ptr); variable_ptr->refcount=1; break; } *variable_ptr_ptr = value; value->refcount++; break; case IS_TMP_VAR: ALLOC_ZVAL(*variable_ptr_ptr); value->refcount=1; **variable_ptr_ptr = *value; break; EMPTY_SWITCH_DEFAULT_CASE() } } (*variable_ptr_ptr)->is_ref=0; } The first if: if the left variable (represented by the pointer variable_ptr) is a reference, the value is assigned to the reference. Otherwise (here we go, the variable is NOT a reference): First, the refcount is decreased, because the variable gets a new value. If then the refcount is zero, the allocated memory for variable_ptr is reused. If the refcount is not zero, we cannot do this, as we would overwrite all other variables (remember: internally, the variable is still stored as a refernce to the value it has been assigned before) In this case, it is checked if the value (that shall be assigned to the variable) itself is a reference. If this is the case, it gets copied to the memory space of the variable pointer. (NOTE: a TMP_VAR is a literal (i.e. a number, string, NULL or boolean written DIRECTLY into the code, like $foo = 5;), a CONST is a variable, i.e. sth like $foo = $bar;) After that, the memory adress of our variable gets changed to the memory adress of the value assigned, and the reference counter is increased :) So we have evidence: definitely a reference, even if not explicitely assigned as one :) Well, now I am curious what you're gonna say about that ;) Regards, David

« previous php.smarty.dev (#1165) next »