Пример #1 Пример использования функции debug_zval_dump()
<?php
$var1 = 'Hello';
$var1 .= ' World';
$var2 = $var1;
debug_zval_dump($var1);
?>
Результат выполнения приведённого примера:
string(11) "Hello World" refcount(3)
Замечание:
Понимание refcount
Значение refcount
, которое показывает функция,
может вызвать удивление без глубокого понимания деталей работы движка.
Zend Engine подсчитывает ссылки по двум причинам:
-
Оптимизация потребления памяти за счёт техники, которая называется «копирование при записи»,
когда несколько переменных с одним и тем же значением указывают на одну
и ту же копию в памяти. Когда одна переменная изменяется, она указывает на новую
копию в памяти, а счётчик ссылок на оригинал уменьшается на 1.
-
Отслеживание переменных, которые были назначены или переданы по ссылке
(смотрите «Объяснение ссылок»).
Этот счётчик ссылок хранится в отдельной ссылке структуры zval, которая указывает на структуру zval
текущего значения. Функция debug_zval_dump() пока не показывает
эту дополнительную структуру zval.
Поскольку функция debug_zval_dump() принимает входные данные как обычные
параметры, передаваемые по значению, для их передачи будет выполняться
метод копирования при записи: вместо копирования данных счётчик ссылок увеличится
на единицу на время вызова функции. Если бы функция изменила
параметр после получения, то движок сделал бы копию; поскольку это не так,
функция покажет счётчик ссылок на единицу больше, чем в вызывающей области.
Передача параметра также предотвратит отображение функцией debug_zval_dump() переменных,
которые были назначены по ссылке. Чтобы проиллюстрировать это, приведём немного
изменённую версию примера:
Хотя переменные $var1, $var2 и
$var3 связаны как ссылки,
в функцию debug_zval_dump() передаётся только значение.
Это значение обрабатывается один раз набором ссылок и один раз внутри функции debug_zval_dump(),
поэтому счётчик ссылок равен 2.
Дополнительные сложности возникают из-за оптимизаций, которые проводит движок для
разных типов данных. Для ряда типов, например целых чисел, движок не использует «копирование при записи»,
поэтому вообще не показывает счётчик ссылок. В других случаях счётчик refcount показывает дополнительные
копии, которые движок создаёт внутри, например, когда сохраняет литеральную строку или массив
как часть инструкции кода.