views:

42

answers:

1

I have a rather weird 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) ""
*/
+1  A: 

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
Artefacto
That's it, thanks. +1
mattalexx