Рассмотрим следующий код:
class a { public $var1; function disp(){ echo $this->var1; } } $obj1 = new a; echo '<br/>After instantiation into $obj1:<br/>'; xdebug_debug_zval('obj1'); $obj1->var1 = "Hello "; echo '<br/><br/>After assigning "Hello" to $obj->var1:<br/>'; $obj1->disp(); echo "<br/><br/>"; xdebug_debug_zval('obj1');
Выход:
После создания экземпляра в $ obj1:
obj1: (refcount = 1, is_ref = 0) = class a {public $ var1 = (refcount = 2, is_ref = 0) = NULL}После назначения «Hello» в $ obj-> var1:
Здравствуйтеobj1: (refcount = 1, is_ref = 0) = class a {public $ var1 = (refcount = 1, is_ref = 0) = 'Hello'}
По одному:
После создания экземпляра в $ obj1:
obj1: (refcount = 1, is_ref = 0) = class a {public $ var1 = (refcount = 2, is_ref = 0) = NULL}
Почему $obj1->var1
имеет refcount=2
когда есть только один объект класса a?
Это из-за того, как new
оператор выполняет задание? PHP выполняет задание со ссылками. При создании экземпляра с new
символом имя / переменная не ассоциируется с этим экземпляром. Но свойства класса имеют имена. Из этого следует recount=2
?
Если это так, то COW (копия при записи) произошла с неглубокой копией WRT экземпляра класса. Хотя свойства все еще указывают на свойства zval, созданные во время создания экземпляра с использованием new
.
Теперь,
После назначения «Hello» в $ obj-> var1:
Здравствуйтеobj1: (refcount = 1, is_ref = 0) = class a {public $ var1 = (refcount = 1, is_ref = 0) = 'Hello'}
Итак, когда я присваиваю значение свойство $obj1->var1
новому контейнеру zval для этого свойства и, следовательно, refcount=1
?
Означает ли это, что контейнер zval, созданный во время создания экземпляра с использованием new
натюрмортов, но доступ к которому невозможен, поскольку имя символа / переменной не ассоциировано с ним?
Обратите внимание (от xdebug: Variable Display Features ):
debug_zval_dump()
отличается от xdebug_debug_zval()
.
void xdebug_debug_zval ( [string varname [, …]] )
Отображает информацию о переменной .
Эта функция отображает структурированную информацию об одной или нескольких переменных, которая включает в себя информацию о типе, значении и пересчете. Массивы исследуются рекурсивно со значениями. Эта функция реализована иначе, чем функция debug_zval_dump () PHP, чтобы обойти проблемы, которые имеет эта функция, поскольку сама переменная фактически передается функции. Версия Xdebug лучше, так как она использует имя переменной для поиска переменной во внутренней таблице символов и обеспечивает доступ ко всем свойствам напрямую, без необходимости иметь дело с передачей переменной функции. В результате информация, возвращаемая этой функцией, намного точнее, чем функция PHP для отображения информации zval.
UPDATE
: Dec 31th 2011:
Я пытаюсь посмотреть, как распределение памяти происходит при использовании нового . Но сейчас слишком много других вещей, которые я должен сделать прямо сейчас. Надеюсь, что скоро опубликую полезное обновление. До тех пор вот ссылки на код, на который я смотрел:
- typedef union hdr
- register pointer new = malloc (sizeof (header) + размер);
- expr_without_variable: T_NEW class_name_reference
- функция zend_do_fetch_class
Добавление другого экземпляра $obj2 = new a;
увеличивает refcount до 3, а не 4, так что это то, что происходит в результате вызова xdebug_debug_zval. Цель функции xdebug состоит в том, чтобы избежать путаницы от передачи переменной в функцию и (возможно) создания дополнительной ссылки.
К сожалению, это не относится к переменным-членам; для этих zval создается другая ссылка для их экспорта. Поэтому все предостережения и непонятные обстоятельства, перечисленные в примечании к документации debug_zval_dump, по- прежнему применяются к переменным-членам.
Я думаю, что в разделе «Примечание: остерегайтесь пересчета» на следующей странице объясняется следующее: http://php.net/manual/en/function.debug-zval-dump.php
Он показывает, что счетчик ссылок увеличивается, если zend оптимизирует способ его передачи, но затем «оговорка» возникает при вызове copy-on-write, возвращая refcount до 1.
надеюсь, это поможет