[PHP] Objektreferenzen

Dieses Thema im Forum "Webentwicklung" wurde erstellt von myth2806, 10. Januar 2011 .

  1. 10. Januar 2011
    Objektreferenzen

    Hey,

    hab ne konzeptionelle Frage zu PHP ( 5.3.4 ).

    Hier erstmal ein kleiner Testcode
    PHP:
    <? php

    $a 
    = new  StdClass ;
    $a -> foo  1 ;

    $b  $a ;
    $b -> foo  2 ;

    debug_zval_dump ( & $a  );
    debug_zval_dump ( & $b  );

    ?>
    PHP:
    <? php

    $a 
    = new  StdClass ;
    $a -> foo  1 ;

    $b  = & $a // <--- Referenzzeichen eingefügt
    $b -> foo  2 ;

    debug_zval_dump ( & $a  );
    debug_zval_dump ( & $b  );

    ?>
    PHP behandelt eine Zuweisung eines Objektes zu einer neuen Variable ja automatisch als Referenz. Sprich in beiden Fällen wird $b als Referenz auf $a erstellt, was auch dadurch bewiesen ist dass sich das Attribut "foo" in beiden Objekten ändert. Warum ist der Refcounter auf $a und $b jetzt aber im ersten Code bei 2 und im zweiten bei 3? Zu erwarten wäre doch dass der Refcounter in beiden Fällen auf 3 ist.
    Kann mir das mal jemand erklären?

    Ausgabe der Skripte:
    Code:
    &object(stdClass)#1 (1) refcount(2){
     ["foo"]=>
     long(2) refcount(1)
    }
    &object(stdClass)#1 (1) refcount(2){
     ["foo"]=>
     long(2) refcount(1)
    }
    
    Code:
    &object(stdClass)#1 (1) refcount(3){
     ["foo"]=>
     long(2) refcount(1)
    }
    &object(stdClass)#1 (1) refcount(3){
     ["foo"]=>
     long(2) refcount(1)
    }
    
    Grüße
     
  2. 10. Januar 2011
    AW: Objektreferenzen

    zu allererst: call-time pass-by-reference gibts nicht mehr.

    PHP:
    debug_zval_dump ( & $b  );
    ist invalider code, bzw.: zwecklos. kannst du auch in der doku nachlesen.

    zu deinem problem:

    code 1:
    refcount 1 = $a
    refcount 2 = debug_zval_dump

    $b ist in diesem fall die gleiche referenz wie $a

    code 2:
    refcount 1 = $a
    refcount 2 = die referenz auf $a
    refcount 3 = debug_zval_dump

    $b ist in diesem fall eine referenz auf $a (welche eine referenz auf die instanz der klasse stdclass ist)

    würde ich vermuten
     
  3. 11. Januar 2011
    AW: Objektreferenzen

    Hey,

    wegen der pass-by-reference Anmerkung: Stimmt, hab ich grade nicht dran gedacht... wollte das ganze aber nicht auch noch unnötig komplizieren und xdebug_debug_zval() nutzen.

    b2t: wenn es so ist wie du vermutest und $a und $b die gleiche refernz sind... dann müsste das eigendliche Objekt ja von der garbage-collection automatisch entfernt werden sobald ich eines der Variablen lösche und die refcount damit auf 0 sinkt.
    Stattdessen ändert sich die refcount aber nicht.
    Das würde dann bedeuten, dass PHP intern eine zweite Ebene von Zeigern verwenden müsste. Die Variable zeigt auf eine Referenz die wiederum eine andere Variable referenziert... das kann ich mir aber kaum vorstellen.

    Oder wie meinst du das?
     
  4. 11. Januar 2011
    AW: Objektreferenzen

    naja, in c hat ja ein pointer auch eine eigene addresse

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
     int a = 1;
     int *b = &a;
     int *c = &b;
    
     printf("%d", *(int *) *c); // 1
     
     return 0;
    }
    es zeigen also zwei pointer auf das selbe objekt = refcount 2

    oder $b ist eine referenz auf $a ist eine referenz auf stdclass ^^
    frag mal terranova/n0s/pyro usw. wie das in c++ läuft, vielleicht können die dir da bessere auskunft geben, oder du schreibst nen bug-report bei php.net und einer der core-hacker erklärt dir das verhalten (wenn du glück hast)

    ich kann es dir (und mir) nicht erklären. einfach keine referenzen auf objekte erstellen ist wohl die einfachere lösung

    folgendes is auch lustig:
    PHP:
    $foo  = new  stdclass ;
    debug_zval_dump ( $foo );  // refcount = 2 (wie erwartet)

    $foo  = & new  stdclass // dieses feature existiert eigl. garnicht mehr
    debug_zval_dump ( $foo );  // refcount = 1
    {bild-down: http://www.videogamesindonesia.com/articles/bersatu/confused.jpg}
     
  5. 11. Januar 2011
    AW: Objektreferenzen

    Wenn ich mit PHP gearbeitet habe, habe ich bisher immer versucht mich von dem Pointer-Konzept von C und dergleichen fern zu halten weil in der doku ausdrücklich gesagt wird man solle das nicht vergleichen ?( vielleicht hatte der Autor des Artikels aber auch diese Frage nicht vor Augen

    Dass $b eine Referenz auf $a ist kann nicht sein... kann die Variablen in beliebiger Reihenfolge entfernen und der refcount der jeweils anderen ändert sich nicht. Sie scheinen absolut gleichwertig zu sein.

    PHP:
    $foo  = & new  stdclass // dieses feature existiert eigl. garnicht mehr
    Diese Syntax hab ich sowieso noch nie verstanden... was ist denn der unterschied wenn ich das Referenzzeichen weglasse??? Da dürfte sich doch nichts ändern.

    Danke dir schonmal!
     
  6. 11. Januar 2011
    AW: Objektreferenzen

    ganz ehrlich, ich versteh es nicht.

    PHP:
    <? php

    header
    ( 'Content-Type: text/plain' );

    $a  = new  stdclass ;
    $b  $a ;
    $c  = & $a ;
    $d  = & $c ;

    debug_zval_dump ( $a );  // refcount = 1

    unset( $b );

    debug_zval_dump ( $a );  // refcount = 1

    unset( $c );

    debug_zval_dump ( $a );  // refcount = 1

    unset( $d );

    debug_zval_dump ( $a );  // refcount = 2
    ich glaub um das zu verstehen müsste man sich tief in die zend-engine reinlesen und den php-bytecode analysieren.
     
  7. 11. Januar 2011
    AW: Objektreferenzen

    Moment das kann jetzt aber auch so nicht klappen.
    Auch wenn es deprecated ist, muss man hier das Referenzzeichen verwenden da sonst nur eine Kopie der Variable bearbeitet wird.
    Vielleicht sollten wir die xdebug-extension verwenden damit es damit nicht zu problemen kommen kann

    PHP:
    <? php

    // header('Content-Type: text/plain');


    $a  = new  stdclass ;
    $b  $a ;
    $c  = & $a ;
    $d  = & $c ;

    debug_zval_dump (& $a );  // refcount = 4
    xdebug_debug_zval 'a'  );  // refcount = 3

    unset( $b );

    debug_zval_dump (& $a );  // refcount = 4
    xdebug_debug_zval 'a'  );  // refcount = 3

    unset( $c );

    debug_zval_dump (& $a );  // refcount = 3
    xdebug_debug_zval 'a'  );  // refcount = 2

    unset( $d );

    debug_zval_dump (& $a );  // refcount = 2
    xdebug_debug_zval 'a'  );  // refcount = 1
    Aber auch hier ändert sich die refcount beim unsetten von $b nicht ?(
    Blicke das auch nicht...
     
  8. 11. Januar 2011
    AW: Objektreferenzen

    verstehe, deswegen dieses komische ergebnis.

    mit call-time-pass-by-reference wäre ich aber vorsichtig, denn das verhalten ist nicht wirklich "sicher".

    xdebug hingeben ist da schon eine bessere lösung.
     
  9. Video Script

    Videos zum Themenbereich

    * gefundene Videos auf YouTube, anhand der Überschrift.