Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Klatsch und Tratsch (https://www.delphipraxis.net/34-klatsch-und-tratsch/)
-   -   Fehler bei php.net melden? (https://www.delphipraxis.net/153561-fehler-bei-php-net-melden.html)

himitsu 8. Aug 2010 14:38

Fehler bei php.net melden?
 
Mir ist grade ein Fehler in PHP 5 aufgefallen.
(dachte erst das liegt an meinem Code und ich hab alles seit gestern umgegraben und sonstwo gesucht und getestet)

Hab das jetzt alles auf diesen Code zusammengeschrumpft,
PHP-Quellcode:
<?php
  $arr = array('one', 'two', 'tree', 'four', 'five');
  foreach ($arr as &$str) $str = machwas($str);
  foreach ($arr as $str) echo $str;
?>
welches als Ergebnis "one two tree four four" liefert

hierbei ändert sich bei jedem Schritt der letzte Array-Eintrag.
PHP-Quellcode:
<?php
  echo '<pre>';
  $arr = array(' one ', ' two ', ' tree ', ' four ', ' five ');
  print_r($arr);
  echo "\n";
  foreach ($arr as &$str)
    $str = trim($str);
  foreach ($arr as $str) {
    print_r($arr);
    echo "\n$str\n\n";
  }
  print_r($arr);
?>

So, hatte das jetzt erstmal hier gepostet:
http://www.php.net/manual/de/control...each.php#99280

und hab nun auch die Bug-Abteilung gefunden.
jetzt suche ich aber schon 'ne Weile viele Einträge ab, ob die was mit meinem Problem zu tun haben und hab noch Unmassen vor mir, da ich auch nicht genau weiß nach was ich suchen soll.

Kennt schon jemand das Problem oder hat dazu schon einen Eintrag entdeckt?


Ach ja: Selber hab'sch das in PHP 5.2.4 und 5.3.0 reproduzieren können.


[add]
und nun hab'sch och den Grund für die Änderung (aber k.A. auf was die Referenz zeigt)
PHP-Quellcode:
$arr = array(' one ', ' two ', ' tree ', ' four ', ' five ');
foreach ($arr as &$str) $str = trim($str);
var_dump($arr);
Code:
array(5) {
  [0]=> string(3) "one"
  [1]=> string(3) "two"
  [2]=> string(4) "tree"
  [3]=> string(4) "four"
  [4]=> &string(4) "five"
}

SirThornberry 8. Aug 2010 16:04

AW: Fehler bei php.net melden?
 
ganz ehrlich sehe ich das nicht als bug an das kuddelmuttel entsteht wenn bei einer foreach schleife die Variable geändert wird durch welche iteriert wird.
[Edit]
Ich nehms zurück, hab irgendwie schief hin geschaut - sorry
Aber um ehrlich zu sein ist mir rätselhaft warum du vor deiner Schleifenvariablen ein & platzierst. Was willst du eigentlich damit bewirken?

mkinzler 8. Aug 2010 16:07

AW: Fehler bei php.net melden?
 
Eher die Tatsache, dass mann das kann

himitsu 8. Aug 2010 16:09

AW: Fehler bei php.net melden?
 
Aber diese Möglichkeit eines änderbaren Values ist offiziell von denen vorgeschlagen und genau auf php.net hatte ich dieses auch mal irgendwo gefunden und fand es eigentlich recht praktisch.

Zitat:

As of PHP 5, you can easily modify array's elements by preceding $value with &. This will assign reference instead of copying the value.
Aber danke dafür, daß du mich für dieses Zitat nochmal hast nachsehn lassen ... hab grade einen Hinweis mit "unset" gefunden (komisch, der war mir bis eben noch garnicht aufgefallen :oops: ) ... mal sehn ob der hilft.
http://www.php.net/manual/de/control...each.php#99280

[edit]
Ein
PHP-Quellcode:
unset($str);
nach der Schleife hilft wirklich :shock:
Na gut, dann werd ich mal alle forschleifen abgrasen und das einfügen.

SirThornberry 8. Aug 2010 16:18

AW: Fehler bei php.net melden?
 
wieder was gelernt. Ich wusste bis eben nicht das es möglich ist auf diese Art und Weise die Variable zu ändern welche durch iteriert wird.

mkinzler 8. Aug 2010 16:19

AW: Fehler bei php.net melden?
 
Führt auch zur Verwirrung. Ich würde von dieser Möglichkeit besser Abstand nehmen

Daniel 8. Aug 2010 17:27

AW: Fehler bei php.net melden?
 
hm. Ich sah das bisher immer als gewissen Performance-Vorteil. Dürfte doch wohl leichter sein, "nur" den Pointer weiterzuschieben, als immer gleich den gesamten Record zu kopieren. Ich habe viele foreach-Schleifen so aufgebaut, auch wenn ich den Wert gear nicht verändere.

himitsu 8. Aug 2010 18:03

AW: Fehler bei php.net melden?
 
Bei Strings und Objekten handelt PHP das ja anscheinend sowieso schon als referenzzählende Zeiger.

Aber vorallem beim Ändern fand/finde ich es von Vorteil, daß man direkt auf den Wert zugreifen kann und nicht jedesmal wieder über das Ursprungsobjekt/-array gehn zu, wo dann der Wert ja erneut gesucht werden müßte.

PHP-Quellcode:
foreach ($this->Parent->Files as $File)

alcaeus 8. Aug 2010 21:34

AW: Fehler bei php.net melden?
 
Normalerweise kannst du die Bugs direkt unter http://bugs.php.net melden. Ich werd das morgen aber nochmal bei ein paar PHP-Group-nahen Arbeitskollegen zur Sprache bringen.

Greetz
alcaeus

alcaeus 11. Aug 2010 06:31

AW: Fehler bei php.net melden?
 
Hier mal die Antwort eines PHP-Entwicklers (also Entwickler am Core). Ich hab ihm diesen Beispielcode geschickt:
PHP-Quellcode:
$array = array(' one ', ' two ', ' three ', ' four ', ' five ');
foreach ($array as &$str) $str = trim($str);
foreach ($array as $str) echo $str;
Zitat:

[12:03]<anonym>: foreach ($arr as &$str) {
[12:04]<anonym>: du iterierst über das array, bei jedem iterationsschritt machst du $str zu einer referenz auf das aktuelle element.
[12:04]<anonym>: Eine Referez in PHP ist ein Alias, d.h. alle Referenzen sind 100% gleichberechtigt.
[12:05]<anonym>: nun is die iteration zu ende.
[12:05]<anonym>: Was is die Situation?
[12:05]<anonym>: $str is eine Referenz auf das letzte element im Array.
[12:05]<anonym>: Klar.
[12:05]<anonym>: Also geht es weiter:
[12:05]<anonym>: #
[12:05]<anonym>: foreach ($arr as $str) {
[12:06]<anonym>: wir iterieren wieder und weise bei jedem schritt $str das aktuelle element zu.
[12:06]<anonym>: $str ist aber eine Referenz auf das letzte element im Array.
[12:07]<anonym>: d.h. wenn wir im ersten schritt der zweiten Iteration das erste Element aus dem Array nehmen und $str zuweisen ändert sich zugleich dasletzte element im array
[12:07]<anonym>: das schaut also wie array(' one ', ' two ', ' three ', ' four ', 'one') aus
[12:07]<anonym>: im nächsten schritt weisen wir dem letzten element dem letzten zu
[12:07]<anonym>: ...
[12:08]<anonym>: im vorletzten schritt weisen wir dem letzten element das vorletzte element zu
[12:08]<anonym>: array(' one ', ' two ', ' three ', ' four ', ' four ')
[12:08]<anonym>: und im letzten schritt das letzte dem letzten, also ändert sich nichts
[12:09]<anonym>: kannst du auch beobachten indem du ein print_r($arr) in die zweite iteration packst
[12:09]<anonym>: Don't use references and be happy.
[12:10]<anonym>: Alles klar?
Alles klar?

Greetz
alcaeus

himitsu 11. Aug 2010 07:38

AW: Fehler bei php.net melden?
 
So in etwa hab ich diese Auswirkung inzwischen auch mitbekommen.
Mit var_dump, statt print_r (hatte sonst auch immer print_r genommen) sieht man auch noch diese Referenz.

Man könnte ja nun auch fragen, warum PHP nicht am Ende der Schleife diese Referenz selber freigibt. :evil:
(soviel zu Managed-Umgebungen :shock: )

Valle 11. Aug 2010 12:36

AW: Fehler bei php.net melden?
 
Weil PHP nicht das Denken für dich übernimmt. Die Zählvariable am Ende einer Schleife freizugeben gehört IMHO nicht in den Aufgabenbereich des Script-Interpreters. Ich hatte schon ab und zu mal Fälle, in denen ich die Variable danach noch gebraucht habe.

Liebe Grüße,
Valle

himitsu 11. Aug 2010 12:37

AW: Fehler bei php.net melden?
 
Nein, das muß es ja nicht, aber wenn PHP dort eine Referenz einfügt, welche vorher nicht da war, dann sollte es diese auch selber wieder entfernen.

Ist doch wie im Delphi.
> der, wer etwas erstellt, der sollte es auch wieder freigeben

Valle 11. Aug 2010 13:53

AW: Fehler bei php.net melden?
 
Du hast doch selbst den Code geschrieben und PHP dazu angewiesen eine Referenz anstatt einer Kopie zu benutzen. Der Interpreter macht genau das, was du ihm gesagt hast. Auch an dieser Stelle muss ich PHP mal in Schutz nehmen, denn es ist völlig logisches und absehbares Verhalten.

Liebe Grüße,
Valle

alcaeus 11. Aug 2010 20:01

AW: Fehler bei php.net melden?
 
Lesen und fuer immer merken:
Zitat:

Zitat von alcaeus (Beitrag 1040961)
Zitat:

[12:09]<anonym>: Don't use references and be happy.

Nach der Schleife ist $str ein Pointer auf $array[4]. Das wird auch immer als Referenz verwendet werden.
Wenn du sowas machst:
PHP-Quellcode:
$i = &$blah;
for ($array as $i => $str) doSomething();
Dann darfst du nicht erwarten, dass $i nicht als Referenz benutzt wird.

Das Reference-Konzept von PHP ist bisserl eigenartig, umso wichtiger ist es dass man es versteht bevor man es verwendet. Ich kann dir wirklich nur den Satz von oben erwaehntem Entwickler ans Herz legen. Der Herr arbeitet seit 10 Jahren mit PHP und ist im Core-Team - wenn der sowas sagt dann ist da was dran.

Greetz
alcaeus

alcaeus 20. Aug 2010 14:23

AW: Fehler bei php.net melden?
 
Glueckwunsch - dein Code hats auf den Blog von besagtem Entwickler geschafft, da auch mit einer sehr ausfuehrlichen Erklaerung: http://schlueters.de/blog/archives/1...d-foreach.html

Greetz
alcaeus

himitsu 20. Aug 2010 14:34

AW: Fehler bei php.net melden?
 
Würde PHP aber am Ende der Schleife die Referenz wieder auflösen/entfernen, dann gäbe es dieses "Problemchen" doch aber garnicht?

SirThornberry 20. Aug 2010 14:57

AW: Fehler bei php.net melden?
 
Ich sehe das genau so. Da hat jemand einen Fehler gebaut und schiebt die Schuld auf irgendwelche Umstände anstelle das der Fehler am Ursprung entfernt wird.

Zumindest ich kenne spontan keinen Fall bei dem man das aktuelle Verhalten haben will.
Hingegen kenne ich nur Fälle in dem man genau das Gegenteil will.
Es macht aus meiner Sicht keinen Sinn das man etwas hinschreiben muss ohne das es gar nicht geht. Für mich ist es so als ob man bei Delphi hinter jede Anweisung noch "do" schreiben müsste (und wenn man es nicht macht passiert irgend etwas ganz anderes als die Anweisung mit "do" bewirkt).

alcaeus 20. Aug 2010 16:11

AW: Fehler bei php.net melden?
 
Wenn du das Konstrukt auseinanderdroeselst, dann weisst du nicht mehr dass du in einer Schleife die Zuweisung hattest. Der einzige Fehler den ich da sehe ist die Moeglichkeit, in der Schleife die "Laufvariable" als Referenz zu verwenden. Der Rest macht absolut Sinn. Es waere mindestens genauso falsch, die Referenz nach der Schleife zu killen, v.a. da das sonst nirgends in PHP moeglich ist. Verwende ich in einer Funktion eine Variable dann kann ich die von da an immer benutzen. Eine Variable nur im Schleifenkontext zu erstellen ist in PHP nicht moeglich.
Noch ein Beispiel:
PHP-Quellcode:
foreach ($foo as $bar => &$baz) {
    if (someCondition()) {
        break;
    }
}
$baz->doSomething();
Wenn mir PHP nun die Referenz unterm Arsch wegziehen wuerde, waere das ein sehr ungewohntes Verhalten. Ich gehe davon aus, dass ich in $baz die Referenz zum zuletzt bearbeiteten Array-Element habe, genauso wie ich nach dieser Schleife einen bestimmten Wert fuer $i erwarte:
PHP-Quellcode:
for ($i = 0; $i < $someCount; $i++)
Greetz
alcaeus

himitsu 20. Aug 2010 17:17

AW: Fehler bei php.net melden?
 
Man kann da notfalls auch einfach den Wert kopieren und damit die Referenz ersetzen.
Aber wer nutzt schon eine Schleifenvariable außerhalb der Schleife? (ein Delphianer lernt/macht sowas jedenfalls nicht :zwinker: )


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:46 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz