AttrVal fehlende device undef Prüfung

Begonnen von noansi, 04 März 2023, 00:57:42

Vorheriges Thema - Nächstes Thema

noansi

Hallo Rudolf,

in fhem.pl wird in der Funktion AttrVal($$$) nicht geprüft, ob $d definiert ist.

Das löst einen Stacktrace aus, da in der Funktion auf $attr{undef} zugeriffen wird, wenn $d == undef ist.
Es wird jedoch auch in diesem Fall $default zurück geliefert, somit ist semantisch prinzipiell auch erlaubt, ein undefiniertes $d zu übergeben und den $default als Rückgabe erwarten zu können.

Folgender Änderungsvorschlag vermeidet den Stacktrace:
sub
AttrVal($$$)
{
  my ($d,$n,$default) = @_;
  if (defined($d)) {
    my $a = $attr{$d};
    if (defined($a)) {
      $n = resolveAttrRename($d, $n);
      return $a->{$n} if(defined($a->{$n}));
    }
  }
  return $default;
}


Das trifft ebenso auch auf andere Funktionen, wie ReadingsVal($$$) etc. zu, die einen übergebenen default Wert zurückliefern, falls der gewünschte Wert nicht vorhanden ist.

Eventuell ist es ein von Dir gewünschtes Verhalten, bei diesen Funktionen mit undefinierten device Übergaben einen Stacktrace zu erzeugen. Allerdings prüfst Du in resolveAttrRename, ob $d definiert ist, was mich daran zweifeln lässt.

Hier https://forum.fhem.de/index.php/topic,24436.msg1265657.html#msg1265657 ist es störend aufgefallen, default als Rückgabe wäre aber passend. (Und wo der kaputte devicename her kommt, ist mit den Stacktraces nicht zu klären)

Bei Funktionen ohne default-Wert Übergabe macht der Stacktrace Sinn.
Meiner Ansicht nach ist es jedoch nicht passend zum default-Wert Gedanken bei Funktionen mit Defaultwertvorgabe.

Gruß, Ansgar.

rudolfkoenig

Das Verhalten ist beabsichtigt, sonst kriegt man solche Probleme nicht mit.
resolveAttrName faengt das ab, sonst wird in $defs ein undef Eintrag angelegt durch den Zugriff auf $defs{$d}{TYPE}, was an diversen Stellen zu Problemen fuehrt.

ZitatUnd wo der kaputte devicename her kommt, ist mit den Stacktraces nicht zu klären
Das kann ich nicht nachvollziehen.

noansi

Hallo Rudolf,

ZitatDas Verhalten ist beabsichtigt, sonst kriegt man solche Probleme nicht mit.
Danke für die Info.
Alles klar, also werd ich es bei mir bei Gelegenheit in TSCUL mal abfangen. Kostet zwei bedingte Zuweisungen für den Fall dieses Attributs.

ZitatDas kann ich nicht nachvollziehen.
Der Stacktrace sagt zunächst nur (und logfüllend immer wieder), dass kaputte device Namen genutzt (bzw. in diesem Fall ursächlich ein kaputter/verstümmelter device hash erzeugt) werden und wo es auffällt. Der Code-Suchraum zur eigentlichen Quelle des kaputten hashes bleibt in diesem Fall, wie sicherlich auch in anderen Fällen, leider groß. Mehr wollte ich zur Änderungsabwägung nicht ergänzen.

Gruß, Ansgar.

rudolfkoenig

Stacktrace gibts nur, wenn man es bestellt, sonst gibts nur eine Zeile pro FHEM-Start.
Und im Stacktrace sieht man, wer auf die Idee gekommen ist AttrVal mit undef aufzurufen.
Gibt es ein Fall, wo das OK ist?

noansi

Hallo Rudolf,

der oben genannte Fall war zwar nicht so gewollt, respektive deutet auf eine unsaubere Subhash Abfrage bei einem nicht definierten device Hash an anderer Stelle hin, ohne zuvor zu prüfen, ob der device hash existiert. Das Ergebnis in meiner Funktion mit dem default war aber ok auch für diesen Fall, da einkalkuliert.

Aber ich kann Deine Motivation zu solchen "Fallen" schon verstehen und in anderen Fällen mit direkter Fehlerkette kann es helfen, Fehler einfach auf diese Weise aufzudecken.

Perl hat nun mal den Fallstrick mit ungewolltem Hash anlegen, auch wenn nur lesend auf Subhashes zugegriffen wird. Hat mich auch was an Debugging gekostet, das zu verstehen und zu lernen, von daher ein gern genommer Fehler insbesondere für Perl Anfänger oder beim schnell mal eben was einbauen.

Gruß, Ansgar.

JoWiemann

Zitat von: noansi am 04 März 2023, 20:41:40
Perl hat nun mal den Fallstrick mit ungewolltem Hash anlegen, auch wenn nur lesend auf Subhashes zugegriffen wird.

Das hat mich auch schon mal zwei Tage gekostet. Irgendwie sollte das bei Erklärungen zu Hash immer fett am Anfang stehen.

Grüße Jörg
Jörg Wiemann

Slave: RPi B+ mit 512 MB, COC (868 MHz), CUL V3 (433.92MHz SlowRF); FHEMduino, Aktuelles FHEM

Master: CubieTruck; Debian; Aktuelles FHEM

betateilchen

Die ganze Aufregung um dieses Verhalten einer hash-Variablen kann ich nicht verstehen.
Solche vermeintlichen Merkwürdigkeiten gibt es in perl doch nicht nur bei hashes, sondern auch bei arrays?


  my @a = ();
  $a[1] = "1";
  $a[4] = "4";


Danach hat das array auch 5 Elemente und nicht 2.

Solche Sachen muss man halt wissen und beim Entwickeln berücksichtigen.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

noansi

ZitatDie ganze Aufregung um dieses Verhalten einer hash-Variablen kann ich nicht verstehen.

Das war nicht die Ausgangsfrage.

Es ging effektiv darum, ob man "ungestraft" AttrVal, also eine Systemfunktion, mit beliebigen, also auch undef, Eingangswerten nutzen kann und auch ohne existierendes Attribut oder ohne existierendes device dann einfach nur den mitgegebenen Default Wert als Rückgabe erwarten darf.

Bei einem IO device, dass Air-Daten empfängt, kommt es fast unweigerlich dazu, dass Fremddaten empfangen werden.
Dazu gibt es im Nutzerinteresse dann eher zwangsläufig auch nicht eingerichtete devices.
Dennoch kann es auch bei der Verarbeitung dieser Fremdaten nützlich sein, device bezogene Attribute gültiger devices zu nutzen. Ohne sauber definiertes device gibt es keinen device-Namen und dabei ist es dann zum Interessenskonflikt gekommen, der auch als Bug gewertet werden kann:
Systemfunktion ist "rock solid" und liefert erwarteten Default Wert vs. Systemfunktion macht auf vermeintliche Probleme aufmerksam (liefert aber ebenfalls den Default).

Gruß, Ansgar.

betateilchen

#8
Zitat von: noansi am 05 März 2023, 14:02:59
Das war nicht die Ausgangsfrage.

Schon klar, aber der Thread hat sich halt in diese Richtung entwickelt.

Zitat von: noansi am 05 März 2023, 14:02:59
Es ging effektiv darum, ob man "ungestraft" AttrVal, also eine Systemfunktion, mit beliebigen, also auch undef, Eingangswerten nutzen kann

Ich verstehe immer noch nicht, warum man eine Funktion wie AttrVal() mit einem "undef" als deviceName aufrufen sollte.
Da ist doch entweder im Konzept oder im Vorfeld des Aufrufs etwas schiefgegangen.
Meiner Meinung nach ist es nicht zwingend die Aufgabe von fhem.pl, jeden von Entwicklern verursachten "Unfug" (nicht böse gemeint!) abzufangen.

Aber das ist ja inzwischen auch schon hier im Thread geklärt.


--
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

noansi

ZitatMeiner Meinung nach ist es nicht zwingend die Aufgabe von fhem.pl, jeden von Entwicklern verursachten "Unfug" (nicht böse gemeint!) abzufangen.

Abfangen tut fhem.pl doch in der Funktion zum Schutz der Systemdatenstrukturen vor Entwicklern, die Unfug treiben, hinterlässt aber dabei ein Spur im Log, die erwünscht und hilfreich sein kann oder auch nicht.

ZitatIch verstehe immer noch nicht, warum man eine Funktion wie AttrVal() mit einem "undef" als deviceName aufrufen sollte.
Z.B. weil es als Zwischenergebnis ohnehin gerade zur Verfügung steht und die Schutzfunktion damit ausgenutzt werden kann!

Gruß, Ansgar.