使用Memcached的set方法时,看似不可能的PHP变量引用行为

时间:2010-09-13 00:42:18

标签: php pass-by-reference memcached

我有一个相当奇怪的问题。由于certain PECL bug,我将var传递给memcached并且它会被更改。建议的解决方法是传递$data.''而不是$data,这会破坏参考。但这对我不起作用,因为我不只是将字符串传递给memcached,而是传递所有数据类型。

所以我最终分配了一个新变量,如$dataPass = $data并传递$dataPass。但是真的很奇怪:

// ...

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) ""
*/

1 个答案:

答案 0 :(得分:1)

如果我正确理解了错误,问题是memcache扩展会在进行修改之前直接修改传递的值而不是复制(即,它不会将值分开)。

在这种情况下,这个:

$dataPass = $data;
除了递增引用计数之外,

绝对没有任何作用。请参阅reference counting basics

强制分离的一种方法是创建一个引用集,然后将其分解:

$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