Почему счетчик ссылок равен 2, а не 1?

  $var = 1;
  debug_zval_dump($var);

Вывод:

long(1) refcount(2)


  $var = 1;
  $var_dup = &$var;
  debug_zval_dump($var);exit;

Вывод :

long(1) refcount(1)

ОБНОВЛЕНИЕ

Очень разочарован ответом...


person ajx    schedule 19.11.2010    source источник
comment
Дословный ответ на php.net/manual/en /function.debug-zval-dump.php#example-5193   -  person Pacerier    schedule 07.08.2013


Ответы (5)


void debug_zval_dump (смешанный $variable);


Код:

$var = 1;              # $var's Refcount = 1
debug_zval_dump($var); # $var is passed by refrence intarlly.

Вывод:

long(1) refcount(2)

Объяснение: Поскольку счетчик ссылок $var равен 1, PHP оптимизирует это и обрабатывает память напрямую, а не делает копию, потому что нет возможности испортить какие-либо другие ссылки. PHP внутренне передает $var по ссылке, так что он может напрямую редактировать память, если это необходимо. Вторая ссылка создается при фактическом вызове debug_zval_dump().

Число ссылок, равное 2, здесь крайне неочевидно. Так что же происходит?

Когда переменная имеет единственную ссылку (как это было с $var до того, как она использовалась в качестве аргумента для debug_zval_dump()), движок PHP оптимизирует способ, которым она передается в функцию. Внутренне PHP обрабатывает $var как ссылку (в том смысле, что счетчик ссылок увеличивается для области действия этой функции), с оговоркой, что если происходит запись переданной ссылки, делается копия, но только в момент записи. . Это известно как «копирование при записи».

Таким образом, если debug_zval_dump() записывает в свой единственный параметр (а это не так), то будет создана копия. До тех пор параметр остается ссылкой, в результате чего счетчик ссылок увеличивается до 2 для области вызова функции.


Код:

$var = 1;              # $var's Refcount = 1
$var_dup = &$var;      # $var's Refcount = 2
debug_zval_dump($var); # A copy is passed as $var's refcount is 2.

Вывод:

long(1) refcount(1)

Объяснение: на этот раз копия $var создается при вызове функции. Это связано с тем, что на $var ссылаются дважды, и PHP не хочет загрязнять любые другие ссылки, поэтому он создает копию $var для собственной работы. Поскольку теперь есть отдельная часть памяти, которая используется только для области вызова функции, у нее есть только одна ссылка, это self. Таким образом, для области действия функции счетчик ссылок копии равен 1 (сам).

person Mark Tomlin    schedule 19.11.2010
comment
Я привел другой пример. - person ajx; 19.11.2010
comment
И это полностью описано в инструкции. php.net/manual/en/function.debug-zval-dump. php - person Mark Tomlin; 19.11.2010
comment
@ajx, я обновил ответ. Надеюсь, теперь вы понимаете. Я хотел бы отметить, что вы не понимаете, как PHP обрабатывает переменные внутри. Я понимаю, что это трудно понять без знания того, как синтаксический анализатор PHP и среда выполнения обрабатывают переменные в рамках функций. Я надеюсь, что это имеет больше смысла, чем последнее обновление, которое у меня было. - person Mark Tomlin; 20.11.2010
comment
@ajx, я действительно не знаю, что тебе сказать на данный момент. Я в значительной степени сделал ответ настолько читабельным, насколько мог. - person Mark Tomlin; 25.11.2010
comment
@Mark: Почему вы даете 500 наград за этот вопрос? Кажется, уже достаточно ответили в руководстве (и здесь). - person NikiC; 19.04.2011
comment
@nikic, ОП не понравился ответ, интересно, что сообщество думает о моем ответе. Я думаю, что сделал все, что мог, но я все еще не получил ответ, поэтому мне интересно, будет ли кто-то еще, и предложение награды в 500 уделит этому вопросу внимание. - person Mark Tomlin; 20.04.2011
comment
@Mark: Если я не ошибаюсь, вы потеряете 500 баллов, поскольку (а) вы не получите очки обратно, если присудите награду себе, и (б) ваш ответ был опубликован до вас выдал вознаграждение, поэтому ваш ответ не подлежит автоматическому награждению. - person phooji; 20.04.2011
comment
@phooji, как бы то ни было, этот вопрос оставляет за собой ответ. - person Mark Tomlin; 21.04.2011

Я думаю, что документация для этого метода объясняет это в разделе «Остерегайтесь счетчика ссылок»:

debug_zval_dump

person Steve Sheldon    schedule 22.04.2011

Код:

$var = 1;
debug_zval_dump($var);

Вывод: long(1) refcount(2)

Объяснение: когда переменная имеет единственную ссылку, как это было с $var до того, как она использовалась в качестве аргумента для debug_zval_dump(), движок PHP оптимизирует способ, которым она передается в функцию. PHP, в основном, создает указатель на переменную, и внутренне PHP обрабатывает $var как ссылку, поэтому его refcount увеличивается для области действия этой функции.

Код:

$var = 1;
$var_dup = &$var;
debug_zval_dump($var);exit;

Вывод: long(1) refcount(1)

Объяснение: здесь переменная $var копируется при записи, создавая совершенно новый отдельный экземпляр этой переменной, и поскольку debug_zval_dump имеет дело с совершенно новой копией $var, а не со ссылкой, ее refcount равен 1. Затем копия уничтожается после выполнения функции.

Надеюсь, это проясняет ситуацию.

person Mark Tomlin    schedule 25.04.2011

Я попытаюсь пролить больше света на функцию debug_zval_dump() и на то, как вы обрабатываете свои переменные. Не убивайте меня, если я ошибаюсь :)...

  $var = 1;
  debug_zval_dump($var);

Я думаю, что функция отладки считает $var refcount(1) и 1 refcount(2), поскольку 1 является значением $var.
Если вы посмотрите на это логически, вы на самом деле говорите это.

  1 = 1;
  debug_zval_dump(1);

Вторая часть:

$var = 1;
$var_dup = &$var;
debug_zval_dump($var);exit;

Здесь вы видите, что вы установили $var в $var_dup, но сохранили его значение. Счетчик ссылок $var равен 1, потому что вы «связали» его с $var_dup.

$var = 2;
$var_dup = &$var; //or $var = &$var_dup; (doesn't matter which one)
$var = 3;
debug_zval_dump($var_dup);exit;

Это дает long(3) refcount(1)... Почему это refcount 1? Как видите, значение $var_dup никогда не было равно 3, оно должно быть равно 2, верно? Нет, не должно, потому что вы постоянно обновляете его с помощью &$var. Это означает, что когда вы пройдете $var = 4 между $var = 3 и debug_zval_dump($var_dup);exit;, значение $var_dup будет автоматически обновлено, потому что вы связали их, сделав его 1 refcount.

Тогда есть еще один случай:

$var = 2;
$var_dup = $var;
$var = 4;
debug_zval_dump($var_dup);exit;

Результат этого: long(2) refcount(2). Как видите, значение $var_dup верное. $var было 2, значение было передано через $var_dup, и он придерживался его. Счетчик ссылок равен 2, потому что он считает $var = 4; и $var_dup = $var;. Когда мы удаляем $var = 4;, мы получаем это:

$var = 2;
$var_dup = $var;
debug_zval_dump($var_dup);exit;

Результат этого: long(2) refcount(3). Теперь функция отладки считает следующее: $var_dup(1), =$var(2) (поскольку $var_dup происходит от $var) и $var(= 2;)(3).

Надеюсь, вы понимаете, что я имею в виду. На мой взгляд, это больше математика, чем программирование, поэтому может быть причиной того, что эту функцию сложно понять.

И еще раз, если я ошибаюсь, не убивайте меня :)...
Приветствую,
Mixxiphoid

Отказ от ответственности
Я не знаю, для чего предназначена эта функция. Я на самом деле никогда не слышал об этом до сегодняшнего дня. Так что я не несу ответственности за ненадлежащее использование :).

person Mixxiphoid    schedule 19.04.2011

Число ссылок, равное 2, здесь крайне неочевидно. Особенно с учетом приведенных выше примеров. Так что же происходит?

Когда переменная имеет единственную ссылку (как это было с $var1 до того, как она использовалась в качестве аргумента для debug_zval_dump()), движок PHP оптимизирует способ, которым она передается в функцию. Внутри PHP обрабатывает $var1 как ссылку (в том смысле, что счетчик ссылок увеличивается для области действия этой функции), с оговоркой, что если происходит запись переданной ссылки, делается копия, но только в момент записи. . Это известно как «копирование при записи».

Таким образом, если debug_zval_dump() записывает в свой единственный параметр (а это не так), то будет создана копия. До тех пор параметр остается ссылкой, в результате чего счетчик ссылок увеличивается до 2 для области вызова функции.

-- Кредиты относятся к руководству по php. Прочтите полное описание этой функции, и вы должны были даже спросить об этом.

--- Редактировать: Упс, я должен прочитать больше комментариев, прежде чем отвечать: D В любом случае, это ответ на вопрос, как упоминалось ранее.

person Jort van Breda    schedule 19.04.2011