PHP: как правильно скопировать примитив на новый адрес памяти

Недавно у меня возникла проблема (PHP: значение переменной загадочным образом установлено на 0 ), где переменная передавалась по значению в функцию PHP, и каким-то образом значение этой переменной было изменено, например:

$var = 'hello';
some_function($var);
echo $var; // outputs 0

Было высказано предположение, что это старая функция, написанная на C, и внутри она что-то делала, чтобы испортить переменную, поскольку в C, по-видимому, вы можете делать такие вещи. Во всяком случае, я попытался сначала скопировать значение, а затем передать его, например:

$var = 'hello';
$var2 = $var;

some_function($var2);
echo $var; // Still outputs 0

Конечно, это не помогло, потому что, когда я читал здесь PHP просто указывает $var2 в таблице символов на тот же контейнер zval, что и $var, и увеличивает счетчик ссылок этого контейнера zval. Конечно, если $var2 переназначить "по значению", для него надо создать новый zval-контейнер, но это не было обычным назначением по значению, судя по всему (об этом немного было в предыдущем вопросе с магическим методом __set() вещь). Я предположил, что что-то происходит с адресом физической памяти, по которому хранится значение, а не присваивание, происходящее через обычный механизм PHP, и, таким образом, все, что указывает на этот zval, будет затронуто. Очень хорошо.

Мой обходной путь состоял в том, чтобы найти способ клонировать примитив $var. Извините, если это повторение, но я нашел массу материала о клонировании классов, но ничего о клонировании примитивов, я думаю, потому что PHP должен делать это правильно автоматически. В итоге я использовал это:

$var = 'hello';

$serialized_var = serialize($var);
$var2 = unserialize($serialized_var);

some_function($var2);
echo $var; // Outputs 'hello', yay!

Мне просто интересно, есть ли лучший способ? Давайте предположим, что нет другого обходного пути, например, использование другой функции или что-то в этом роде, и что мы должны получить настоящую копию переменной. Как можно было это сделать?


person nerdlinger    schedule 22.04.2016    source источник
comment
Похоже, он возвращает его как int.   -  person cpugourou    schedule 22.04.2016
comment
Вы пытались заставить его как строку? settype($var, строка);   -  person cpugourou    schedule 22.04.2016