ΠžΡΠ½ΠΎΠ²Ρ‹ подсчёта ссылок

ΠŸΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Π°Ρ PHP хранится Π² ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π΅, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ называСтся zval (Π°Π½Π³Π». сокр.: Zend Value β€” Zend-Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅). ΠšΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ zval, ΠΊΡ€ΠΎΠΌΠ΅ Ρ‚ΠΈΠΏΠ° ΠΈ значСния ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ, Ρ‚Π°ΠΊΠΆΠ΅ содСрТит Π΄Π²Π° Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Ρ… Π±ΠΈΡ‚Π° ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ. ΠŸΠ΅Ρ€Π²Ρ‹ΠΉ называСтся is_ref (Π°Π½Π³Π». сокр.: Is Reference β€” ссылка Π»ΠΈ?) ΠΈ прСдставляСт логичСскоС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚, Π²ΠΊΠ»ΡŽΡ‡ΠΈΠ» Π»ΠΈ PHP ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ Π² Β«Π½Π°Π±ΠΎΡ€ ссылок» ΠΈΠ»ΠΈ Π½Π΅Ρ‚. Π—Π° счёт Π±ΠΈΡ‚Π° is_ref PHP-Π΄Π²ΠΈΠΆΠΎΠΊ Π·Π½Π°Π΅Ρ‚, ΠΊΠ°ΠΊ ΠΎΡ‚Π»ΠΈΡ‡Π°Ρ‚ΡŒ ΠΎΠ±Ρ‹Ρ‡Π½Ρ‹Π΅ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ ΠΎΡ‚ ссылок. ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ PHP Ρ€Π°Π·Ρ€Π΅ΡˆΠ°Π΅Ρ‚ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΈΠ΅ ссылки, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΡΠΎΠ·Π΄Π°ΡŽΡ‚ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ΠΎΠΌ &, ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ zval Ρ‚Π°ΠΊΠΆΠ΅ содСрТит Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½ΠΈΠΉ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ подсчёта ссылок для ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΈ Ρ€Π°Π±ΠΎΡ‚Ρ‹ памяти. Вторая Ρ‡Π°ΡΡ‚ΡŒ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠΉ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ называСтся refcount (Π°Π½Π³Π». сокр.: Reference Counter β€” счётчик ссылок) ΠΈ содСрТит количСство ΠΈΠΌΡ‘Π½ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ…, ΠΈΠ»ΠΈ Π΄Ρ€ΡƒΠ³ΠΎΠ΅ Π½Π°Π·Π²Π°Π½ΠΈΠ΅ β€” символов, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΡƒΠΊΠ°Π·Ρ‹Π²Π°ΡŽΡ‚ Π½Π° этот zval-ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€. ΠšΠ°ΠΆΠ΄Ρ‹ΠΉ символ хранится Π² Ρ‚Π°Π±Π»ΠΈΡ†Π΅ символов. Π£ ΠΊΠ°ΠΆΠ΄ΠΎΠΉ области видимости ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ… своя Ρ‚Π°Π±Π»ΠΈΡ†Π° символов. PHP создаёт ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΡƒΡŽ ΠΎΠ±Π»Π°ΡΡ‚ΡŒ видимости для Π³Π»Π°Π²Π½ΠΎΠ³ΠΎ скрипта, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ срабатываСт ΠΏΡ€ΠΈ запросС ΠΈΠ· Π±Ρ€Π°ΡƒΠ·Π΅Ρ€Π°, ΠΈ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΡƒΡŽ ΠΎΠ±Π»Π°ΡΡ‚ΡŒ видимости для ΠΊΠ°ΠΆΠ΄ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΈΠ»ΠΈ ΠΌΠ΅Ρ‚ΠΎΠ΄Π°.

ΠšΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ zval создаётся ΠΏΡ€ΠΈ объявлСнии Π½ΠΎΠ²ΠΎΠΉ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ присваиваСтся константноС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€:

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ #1 Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ Π½ΠΎΠ²ΠΎΠ³ΠΎ ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π° zval

<?php

$a
= "new string";

?>

Π’ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ области видимости создаётся Π½ΠΎΠ²Ρ‹ΠΉ символ с ΠΈΠΌΠ΅Π½Π΅ΠΌ "a" ΠΈ Π½ΠΎΠ²Ρ‹ΠΉ ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ с Ρ‚ΠΈΠΏΠΎΠΌ string ΠΈ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ new string. Π‘ΠΈΡ‚ is_ref ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ задаётся Ρ€Π°Π²Π½Ρ‹ΠΌ false, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Π½Π΅ создали Π½ΠΈ ΠΎΠ΄Π½ΠΎΠΉ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΎΠΉ ссылки. Π—Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΆΠ΅ Π±ΠΈΡ‚Π° refcount задаётся Ρ€Π°Π²Π½Ρ‹ΠΌ 1, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ с этим ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ΠΎΠΌ PHP связал Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΠ΄ΠΈΠ½ символ. ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, zval-ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Ρ‹ со Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ true Π² Π±ΠΈΡ‚Π΅ is_ref ΠΈ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ 1 Π² Π±ΠΈΡ‚Π΅ refcount Π΄Π²ΠΈΠΆΠΎΠΊ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Ρ‹Π²Π°Π΅Ρ‚ Π² ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Ρ‹ стандартных ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ… ΠΏΡƒΡ‚Ρ‘ΠΌ установки для Π±ΠΈΡ‚Π° is_ref значСния false. ΠœΠΎΠ΄ΡƒΠ»ΡŒ » Xdebug ΡƒΠΌΠ΅Π΅Ρ‚ Π²Ρ‹Π²ΠΎΠ΄ΠΈΡ‚ΡŒ эту ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ Ρ‡Π΅Ρ€Π΅Π· Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ xdebug_debug_zval().

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ #2 Π’Ρ‹Π²ΠΎΠ΄ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ ΠΎ zval-ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π΅

<?php

$a
= "new string";
xdebug_debug_zval('a');

?>

Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния ΠΏΡ€ΠΈΠ²Π΅Π΄Ρ‘Π½Π½ΠΎΠ³ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°:

a: (refcount=1, is_ref=0)='new string'

ΠŸΡ€ΠΈΡΠ²Π°ΠΈΠ²Π°Π½ΠΈΠ΅ ΠΎΠ΄Π½ΠΎΠΉ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ Π΄Ρ€ΡƒΠ³ΠΎΠΌΡƒ ΠΈΠΌΠ΅Π½ΠΈ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΠ²Π°Π΅Ρ‚ счётчик ссылок.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ #3 Π£Π²Π΅Π»ΠΈΡ‡Π΅Π½ΠΈΠ΅ счётчика ссылок ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π° zval

<?php

$a
= "new string";
$b = $a;
xdebug_debug_zval('a');

?>

Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния ΠΏΡ€ΠΈΠ²Π΅Π΄Ρ‘Π½Π½ΠΎΠ³ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°:

a: (refcount=2, is_ref=0)='new string'

Π—Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ счётчика ссылок здСсь Ρ€Π°Π²Π½ΠΎ 2, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ с ΠΎΠ΄Π½ΠΈΠΌ ΠΈ Ρ‚Π΅ΠΌ ΠΆΠ΅ ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ΠΎΠΌ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ PHP связал ΠΊΠ°ΠΊ символ a, Ρ‚Π°ΠΊ ΠΈ символ b. PHP достаточно ΡƒΠΌΡ‘Π½, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π½Π΅ ΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ сам ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€, ΠΏΠΎΠΊΠ° этого Π½Π΅ трСбуСтся. Как Ρ‚ΠΎΠ»ΡŒΠΊΠΎ счётчик ссылок refcount становится Ρ€Π°Π²Π½Ρ‹ΠΌ Π½ΡƒΠ»ΡŽ, ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Ρ‹ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ… ΡƒΠ½ΠΈΡ‡Ρ‚ΠΎΠΆΠ°ΡŽΡ‚ΡΡ. Π‘Ρ‡Ρ‘Ρ‚Ρ‡ΠΈΠΊ ссылок refcount ΡƒΠΌΠ΅Π½ΡŒΡˆΠ°Π΅Ρ‚ΡΡ Π½Π° Π΅Π΄ΠΈΠ½ΠΈΡ†Ρƒ, ΠΊΠΎΠ³Π΄Π° символ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ PHP связал с ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ΠΎΠΌ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ, Π²Ρ‹Ρ…ΠΎΠ΄ΠΈΡ‚ ΠΈΠ· области видимости (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Π² ΠΊΠΎΠ½Ρ†Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ), ΠΈΠ»ΠΈ ΠΏΡ€ΠΈ ΡƒΠ΄Π°Π»Π΅Π½ΠΈΠΈ символа (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ΠΏΡ€ΠΈ Π²Ρ‹Π·ΠΎΠ²Π΅ языковой конструкции unset()).

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ #4 УмСньшСниС счётчика ссылок ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π° zval

<?php

$a
= "new string";
$c = $b = $a;
xdebug_debug_zval('a');

$b = 42;
xdebug_debug_zval('a');

unset(
$c );
xdebug_debug_zval('a');

?>

Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния ΠΏΡ€ΠΈΠ²Π΅Π΄Ρ‘Π½Π½ΠΎΠ³ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°:

a: (refcount=3, is_ref=0)='new string'
a: (refcount=2, is_ref=0)='new string'
a: (refcount=1, is_ref=0)='new string'

Π’Ρ‹Π·ΠΎΠ² unset($a); Π² этом мСстС ΡƒΠ΄Π°Π»ΠΈΡ‚ ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ ΠΈΠ· памяти, Π²ΠΊΠ»ΡŽΡ‡Π°Ρ Ρ‚ΠΈΠΏ ΠΈ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅.

БоставныС Ρ‚ΠΈΠΏΡ‹ Π΄Π°Π½Π½Ρ‹Ρ…

Π₯Ρ€Π°Π½Π΅Π½ΠΈΠ΅ составных Ρ‚ΠΈΠΏΠΎΠ² Π΄Π°Π½Π½Ρ‹Ρ… Π½Π°ΠΏΠΎΠ΄ΠΎΠ±ΠΈΠ΅ массивов (array) ΠΈ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ² (object) услоТняСтся. ΠšΠ°ΠΆΠ΄Ρ‹ΠΉ элСмСнт массива ΠΈΠ»ΠΈ ΠΊΠ°ΠΆΠ΄ΠΎΠ΅ свойство ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° хранится Π² ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΉ Ρ‚Π°Π±Π»ΠΈΡ†Π΅ символов, Π² ΠΏΡ€ΠΎΡ‚ΠΈΠ²ΠΎΠΏΠΎΠ»ΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ Ρ…Ρ€Π°Π½Π΅Π½ΠΈΡŽ скалярных (scalar) Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ ΠΎΠ΄Π½ΠΎΠΉ ΠΈ Ρ‚ΠΎΠΉ ΠΆΠ΅ области видимости Π² ΠΎΠ΄Π½ΠΎΠΉ Ρ‚Π°Π±Π»ΠΈΡ†Π΅ символов. Π‘Π»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ создаст сразу Ρ‚Ρ€ΠΈ zval-ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π°:

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ #5 Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ zval-ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π° для массива (array)

<?php

$a
= array('meaning' => 'life', 'number' => 42);
xdebug_debug_zval('a');

?>

Π’Ρ‹Π²ΠΎΠ΄ ΠΏΡ€ΠΈΠ²Π΅Π΄Ρ‘Π½Π½ΠΎΠ³ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠΎΡ…ΠΎΠΆ Π½Π°:

a: (refcount=1, is_ref=0)=array (
   'meaning' => (refcount=1, is_ref=0)='life',
   'number' => (refcount=1, is_ref=0)=42
)

ГрафичСски:

ΠšΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Ρ‹ для простого массива

PHP создаёт Ρ‚Ρ€ΠΈ zval-ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π° для символов: a, meaning ΠΈ number. АналогичныС ΠΏΡ€Π°Π²ΠΈΠ»Π° ΠΏΡ€ΠΈΠΌΠ΅Π½ΡΡŽΡ‚ΡΡ для увСличСния ΠΈ ΡƒΠΌΠ΅Π½ΡŒΡˆΠ΅Π½ΠΈΡ количСства ссылок. Π’ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΌ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ Π² массив добавляСтся Π΅Ρ‰Ρ‘ ΠΎΠ΄ΠΈΠ½ элСмСнт, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌΡƒ устанавливаСтся Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Π΄Ρ€ΡƒΠ³ΠΎΠ³ΠΎ элСмСнта массива:

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ #6 Π”ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ ΡƒΠΆΠ΅ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰Π΅Π³ΠΎ элСмСнта Π² массив

<?php

$a
= array('meaning' => 'life', 'number' => 42);
$a['life'] = $a['meaning'];
xdebug_debug_zval('a');

?>

Π’Ρ‹Π²ΠΎΠ΄ ΠΏΡ€ΠΈΠ²Π΅Π΄Ρ‘Π½Π½ΠΎΠ³ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠΎΡ…ΠΎΠΆ Π½Π°:

a: (refcount=1, is_ref=0)=array (
   'meaning' => (refcount=2, is_ref=0)='life',
   'number' => (refcount=1, is_ref=0)=42,
   'life' => (refcount=2, is_ref=0)='life'
)

ГрафичСски:

ΠšΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Ρ‹ для простого массива со ссылками

Из Π²Ρ‹Π²ΠΎΠ΄Π° модуля Xdebug Π²ΠΈΠ΄Π½ΠΎ, Ρ‡Ρ‚ΠΎ ΠΊΠ°ΠΊ старый, Ρ‚Π°ΠΊ ΠΈ Π½ΠΎΠ²Ρ‹ΠΉ элСмСнт массива Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ Π½Π° zval-ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€, Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ refcount ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ Ρ€Π°Π²Π½ΠΎ 2. Π₯отя Π²Ρ‹Π²ΠΎΠ΄ модуля Xdebug ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ Π΄Π²Π° zval-ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π° со Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ 'life', ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Ρ‹ ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²Ρ‹. Ѐункция xdebug_debug_zval() Π½Π΅ ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Ρ‹ ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²Ρ‹, Π½ΠΎ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ Π² Π²Ρ‹Π²ΠΎΠ΄ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»Π΅ΠΉ памяти ΠΏΠΎΠΊΠ°ΠΆΠ΅Ρ‚.

Π­Π»Π΅ΠΌΠ΅Π½Ρ‚ удаляСтся ΠΈΠ· массива Π°Π½Π°Π»ΠΎΠ³ΠΈΡ‡Π½ΠΎ ΡƒΠ΄Π°Π»Π΅Π½ΠΈΡŽ символа ΠΈΠ· области видимости: счётчик ссылок refcount Ρ‚ΠΎΠ³ΠΎ ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π°, Π½Π° ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ элСмСнт массива, ΡƒΠΌΠ΅Π½ΡŒΡˆΠ°Π΅Ρ‚ΡΡ. ΠšΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ удаляСтся ΠΈΠ· памяти, ΠΊΠΎΠ³Π΄Π° Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Π² Π±ΠΈΡ‚Π΅ refcount достигаСт нуля. ΠŸΡ€ΠΈΠΌΠ΅Ρ€:

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ #7 Π£Π΄Π°Π»Π΅Π½ΠΈΠ΅ элСмСнта ΠΈΠ· массива

<?php

$a
= array('meaning' => 'life', 'number' => 42);
$a['life'] = $a['meaning'];
unset(
$a['meaning'], $a['number']);
xdebug_debug_zval('a');

?>

Π’Ρ‹Π²ΠΎΠ΄ ΠΏΡ€ΠΈΠ²Π΅Π΄Ρ‘Π½Π½ΠΎΠ³ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠΎΡ…ΠΎΠΆ Π½Π°:

a: (refcount=1, is_ref=0)=array (
   'life' => (refcount=1, is_ref=0)='life'
)

Битуация станСт интСрСснСС, Ссли Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ массив сам Π² сСбя. Π’ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΌ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ вводится ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ присваивания ΠΏΠΎ ссылкС, Ρ‡Ρ‚ΠΎΠ±Ρ‹ PHP Π½Π΅ создал копию массива.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ #8 ΠŸΡ€ΠΈΠΌΠ΅Ρ€ добавлСния массива ΠΊΠ°ΠΊ элСмСнта самого сСбя

<?php

$a
= array('one');
$a[] =& $a;
xdebug_debug_zval('a');

?>

Π’Ρ‹Π²ΠΎΠ΄ ΠΏΡ€ΠΈΠ²Π΅Π΄Ρ‘Π½Π½ΠΎΠ³ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠΎΡ…ΠΎΠΆ Π½Π°:

a: (refcount=2, is_ref=1)=array (
   0 => (refcount=1, is_ref=0)='one',
   1 => (refcount=2, is_ref=1)=...
)

ГрафичСски:

ΠšΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Ρ‹ массива с цикличСскими ссылками

Π’ΠΈΠ΄Π½ΠΎ, Ρ‡Ρ‚ΠΎ пСрСмСнная массива a, ΠΈ Π²Ρ‚ΠΎΡ€ΠΎΠΉ элСмСнт с индСксом 1 Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ ΡƒΠΊΠ°Π·Ρ‹Π²Π°ΡŽΡ‚ Π½Π° ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ, Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ refcount ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ Ρ€Π°Π²Π½ΠΎ 2. Π‘ΠΈΠΌΠ²ΠΎΠ»Ρ‹ Β«...Β» Π² Π²Ρ‹Π²ΠΎΠ΄Π΅ ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°ΡŽΡ‚ Ρ€Π΅ΠΊΡƒΡ€ΡΠΈΡŽ, Ρ‡Ρ‚ΠΎ Π² этом ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ символы Β«...Β» ΡƒΠΊΠ°Π·Ρ‹Π²Π°ΡŽΡ‚ Π½Π° исходный массив.

Как ΠΈ Ρ€Π°Π½ΡŒΡˆΠ΅, ΠΏΡ€ΠΈ ΡƒΠ΄Π°Π»Π΅Π½ΠΈΠΈ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ символ удаляСтся, Π° счётчик ссылок ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π° ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ, Π½Π° ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ пСрСмСнная, ΡƒΠΌΠ΅Π½ΡŒΡˆΠ°Π΅Ρ‚ΡΡ Π½Π° Π΅Π΄ΠΈΠ½ΠΈΡ†Ρƒ. ΠŸΠΎΡΡ‚ΠΎΠΌΡƒ, Ссли ΠΏΡ€ΠΈΠΌΠ΅Π½ΠΈΡ‚ΡŒ ΠΊΠΎΠ½ΡΡ‚Ρ€ΡƒΠΊΡ†ΠΈΡŽ unset ΠΊ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ $a послС запуска ΠΏΡ€ΠΈΠ²Π΅Π΄Ρ‘Π½Π½ΠΎΠ³ΠΎ ΠΊΠΎΠ΄Π°, счётчик ссылок ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π° ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ, Π½Π° ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΡƒΠΊΠ°Π·Ρ‹Π²Π°ΡŽΡ‚ пСрСмСнная $a ΠΈ элСмСнт массива с индСксом 1, ΡƒΠΌΠ΅Π½ΡŒΡˆΠΈΡ‚ΡΡ Π½Π° Π΅Π΄ΠΈΠ½ΠΈΡ†Ρƒ, с 2 Π΄ΠΎ 1:

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ #9 Π£Π΄Π°Π»Π΅Π½ΠΈΠ΅ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ массива $a

(refcount=1, is_ref=1)=array (
   0 => (refcount=1, is_ref=0)='one',
   1 => (refcount=1, is_ref=1)=...
)

ГрафичСски:

ΠšΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Ρ‹ послС удалСния массива с цикличСскими ссылками, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π΄Π΅ΠΌΠΎΠ½ΡΡ‚Ρ€ΠΈΡ€ΡƒΡŽΡ‚ ΡƒΡ‚Π΅Ρ‡ΠΊΡƒ памяти

ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ очистки

Π₯отя Π½ΠΈ Π² ΠΎΠ΄Π½ΠΎΠΉ области видимости большС Π½Π΅Ρ‚ символа, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ Π½Π° структуру массива, структуру нСльзя ΠΎΡ‡ΠΈΡΡ‚ΠΈΡ‚ΡŒ, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ элСмСнт массива с ΠΊΠ»ΡŽΡ‡ΠΎΠΌ 1 ΠΏΠΎ-ΠΏΡ€Π΅ΠΆΠ½Π΅ΠΌΡƒ ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ Π½Π° этот ΠΆΠ΅ массив. ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Π½Π° структуру Π½Π΅ ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ внСшний символ, ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŽ нСдоступна очистка этой структуры; поэтому ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ ΡƒΡ‚Π΅Ρ‡ΠΊΡƒ памяти. К ΡΡ‡Π°ΡΡ‚ΡŒΡŽ, PHP очистит эту структуру Π΄Π°Π½Π½Ρ‹Ρ… Π² ΠΊΠΎΠ½Ρ†Π΅ запроса, Π½ΠΎ Π΄ΠΎ Ρ‚ΠΎΠ³ΠΎ ΠΌΠΎΠΌΠ΅Π½Ρ‚Π° Π΄Π°Π½Π½Ρ‹Π΅ Π±ΡƒΠ΄ΡƒΡ‚ Π·Π°Π½ΠΈΠΌΠ°Ρ‚ΡŒ Ρ†Π΅Π½Π½ΠΎΠ΅ мСсто Π² памяти. Вакая ситуация часто Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ‚ ΠΏΡ€ΠΈ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌΠΎΠ² синтаксичСского Π°Π½Π°Π»ΠΈΠ·Π° ΠΈΠ»ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΡ… Π²Π΅Ρ‰Π΅ΠΉ, Π² ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΠ΅ элСмСнты ΡƒΠΊΠ°Π·Ρ‹Π²Π°ΡŽΡ‚ Π½Π° Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΡΠΊΠΈΠ΅. Π‘ Π΅Ρ‰Ρ‘ большСй Π²Π΅Ρ€ΠΎΡΡ‚Π½ΠΎΡΡ‚ΡŒΡŽ такая ΠΆΠ΅ ситуация Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ‚ с ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°ΠΌΠΈ, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ с ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°ΠΌΠΈ язык нСявно Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ Β«ΠΏΠΎ ссылкС».

НС ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ°, Ссли Ρ‚Π°ΠΊΠΎΠ΅ случаСтся Ρ€Π°Π· ΠΈΠ»ΠΈ Π΄Π²Π°, Π½ΠΎ ΠΏΡ€ΠΈ тысячС ΠΈΠ»ΠΈ Π΄Π°ΠΆΠ΅ ΠΌΠΈΠ»Π»ΠΈΠΎΠ½Π΅ Ρ‚Π°ΠΊΠΈΡ… случаСв ΡƒΡ‚Π΅Ρ‡ΠΊΠΈ памяти ΡƒΠΆΠ΅ станут ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠΎΠΉ. ОсобСнно Π² скриптах, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚ Π΄ΠΎΠ»Π³ΠΎ, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Π² Π΄Π΅ΠΌΠΎΠ½Π°Ρ…, Π² ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… запрос Π½Π΅ заканчиваСтся, ΠΈΠ»ΠΈ Π² ΠΊΡ€ΡƒΠΏΠ½Ρ‹Ρ… Π½Π°Π±ΠΎΡ€Π°Ρ… ΠΌΠΎΠ΄ΡƒΠ»ΡŒΠ½Ρ‹Ρ… тСстов. ПослСдний случай Π²Ρ‹Π·Π²Π°Π» ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ ΠΏΡ€ΠΈ запускС ΠΌΠΎΠ΄ΡƒΠ»ΡŒΠ½Ρ‹Ρ… тСстов для ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π° Template Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ ez Components. Π’ рядС случаСв Ρ‚Ρ€Π΅Π±ΠΎΠ²Π°Π»ΠΎΡΡŒ большС 2 Π“Π‘ памяти, доступа ΠΊ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ Π½Π° тСстовом сСрвСрС Π½Π΅ Π±Ρ‹Π»ΠΎ.

οΌ‹Π”ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ

ΠŸΡ€ΠΈΠΌΠ΅Ρ‡Π°Π½ΠΈΡ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ 6 notes

up
18
Anonymous ΒΆ
11 years ago
There seems to be no way to inspect the reference count of a specific class variable but you can view the reference count of all variables in the current class instance with xdebug_debug_zval('this');
up
9
shkarbatov at gmail dot com ΒΆ
8 years ago
Result of "Example #8 Adding the array itself as an element of it self" will be another for PHP7:

a: (refcount=2, is_ref=1)=array (
    0 => (refcount=2, is_ref=0)='one',
    1 => (refcount=2, is_ref=1)=...
)

insted of:
a: (refcount=2, is_ref=1)=array (
   0 => (refcount=1, is_ref=0)='one',
   1 => (refcount=2, is_ref=1)=...
)

Internal value representation in PHP 7:
https://nikic.github.io/2015/05/05/Internal-value-representation-in-PHP-7-part-1.html
up
10
Anonymous ΒΆ
11 years ago
If a variable is not present in the current scope xdebug_debug_zvalγ€€will return null.
up
6
skymei at skymei dot cn ΒΆ
6 years ago
$a = 'new string';
$b = 1;
xdebug_debug_zval('a');
xdebug_debug_zval('b');

ouputs with PHP 7.3.12 (cli) 

a: (interned, is_ref=0)='new string'
b: (refcount=0, is_ref=0)=1
up
1
yuri1308960477 at gmail dot com ΒΆ
7 years ago
my php versoin : HP 7.1.25 (cli) (built: Dec  7 2018 08:20:45) ( NTS )

$a = 'new string';
$b = 1;
xdebug_debug_zval('a');
xdebug_debug_zval('b');

output:

a: (refcount=2, is_ref=0)='new string'
b: (refcount=0, is_ref=0)=1

if $a is a string value, 'refcount' equal 2 by defalut.
up
-2
chxt2011 at 163 dot com ΒΆ
7 years ago
my php version is PHP 7.1.6 (cli), when I run 

$a = 'new string';
$b = 1;
xdebug_debug_zval('a');
xdebug_debug_zval('b');

it shows:
a: (refcount=0, is_ref=0)='new string'
b: (refcount=0, is_ref=0)=1