Seemingly impossible PHP variable referencing behavior when using Memcached's set method
I have a rather we开发者_如何学Pythonird problem. Because of a certain PECL bug, I pass a var into memcached and it gets changed. The suggested workaround is to pass $data.''
instead of $data
and that destroys the reference. But that won't work for me because I don't just pass strings into memcached, I pass all data types.
So I ended up assigning a new variable like $dataPass = $data
and passing $dataPass
. But something really weird is happening:
// ...
var_dump("data 1");
var_dump($data);
$dataPass = $data; // Dereferencing the variable
// because of http://pecl.php.net/bugs/bug.php?id=14239
var_dump("data 2");
var_dump($data);
var_dump("dataPass 2");
var_dump($dataPass);
$this->memcache->set($key, $dataPass, false, time() + $expire);
var_dump("data 3");
var_dump($data);
var_dump("dataPass 3");
var_dump($dataPass);
/*
string(11) "data 1"
bool(false)
string(22) "data 2"
bool(false)
string(26) "dataPass 2"
bool(false)
string(10) "data 3"
string(0) "" <--- Why is this not bool(false)?
string(14) "dataPass 3"
string(0) ""
*/
If I understand the bug correctly, the problem is that the memcache extension modifies the passed value directly instead of copying before doing the modifications (i.e., it doesn't separate the value).
In that case, this:
$dataPass = $data;
does absolutely nothing besides incrementing the reference count. See reference counting basics.
One way to force the separation, would be to create a reference set and then break it:
$data = false; //$data's zval: refcount 1, is_ref 0
$dataPassPre =& $data; //$data/$dataPassPre zval: refcount 2, is_ref 1
//equivalently to below: $dataPass = $dataPassPre;
$dataPass = $data; //$dataPass's zval: has refcount 1, is_ref 0
unset($dataPassPre); //restore $data's zval to refcount 1, is_ref 0
//now pass $dataPass
精彩评论