开发者

Seemingly impossible PHP variable referencing behavior when using Memcached's set method

开发者 https://www.devze.com 2023-01-16 01:56 出处:网络
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 th

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
0

精彩评论

暂无评论...
验证码 换一张
取 消