Roland Goretzki schrieb:
In dem speziellen Fall von 2. zumindestens denke ich, daß eine mögliche Fehlerquelle auszuschlossen wird, wenn ich z.B. mit ReadStr diese Variable wieder zu LongInt machen möchte.
Aber halt nur eine. Der String kann immer noch nicht-Ziffern enthalten,
Hier noch einmal: Wo sollen die herkommen, wenn der String so entsteht, daß er als Zahl in einer Datei abgelegt wird (wo diese natürlich als String "ihr Dasein fristet" (;-), um anschließend mit ReadLn als Zahl wieder eingelesen zu werden.
Blöde Antwort: Jemand hat die Datei manuell verändert, z.B. wollte jemand den Inhalt der Datei prüfen (z.B. um ein Problem zu suchen), und hat sie (z.B. aus Bequemlichkeit) einfach im Texteditor geöffnet (nicht read-only) und (z.B. durch Vertippen, unbemerkt) etwas darin geändert. Erlebt habe ich schon Vieles (und oft war ich dann selbst der Jemand ;-).
Also ich denke folgendermaßen: Wenn es in diesem Fall möglich wäre, daß dem String andere Zeichen als nur Ziffern durch irgendeinen mysteriösen Vorgang "untergeschoben" werden können, dann wäre bestimmt noch niemand zum Mond geflogen, weil man sich beim Rechner auf gar nichts mehr verlassen könnte.
Das geht natürlich etwas weiter, aber in der Tat werden (SWIW) in der Raumfahrt eher ältere Prozessoren eingesetzt, da die neueren störanfälliger sind. Dann gibt es natürlich redundante Systeme, Schutz vor Weltraumstrahlung usw. Aber die Probleme, die ich hier meine, sind eher menschliche Fehler (auf Seiten des Programmierers und/oder Nutzers). Auch diese kommen natürlich in der Raumfahrt vor, obwohl die Programme dort sicher wesentlich gründlicher geprüft und getestet werden, als wir das normalerweise können, s. z.B. http://de.wikipedia.org/wiki/Ariane_V88
also besteht die Möglichkeit von Laufzeitfehlern immer noch. (Natürlich könnte man das vorher noch testen, aber dann ist es wiederum einfacher, "Val" oder so zu verwenden, das einem gleich sagt, ob die Umwandlung erfolgreich war.)
Wenn überhaupt, dann scheint das in meinem Fall das geeignete Mittel zum Fehlerabfangen sein.
Wie schon früher gesagt, würde ich auch entweder "Val" empfehlen (wenn du auf den Fehler reagieren willst) oder "ReadStr", wenn ein Programmabbruch im Fehlerfall OK ist (während "StrReadInt" bei manchen Fehlern eben mit falschen Ergebnissen weitermachen würde, insbes. bei Müll am Ende).
[StrReadInt]
Nun kann ich die Funktion korrekt aufrufen. Das hat zwar lange gedauert, aber ich glaube, daß ich es jetzt zum großen Teil verstanden habe: Also, die Funktion liefert NUR den Wert FALSE zurück, wenn keine Zahl aus dem String gelesen werden kann, anderenfalls aber TRUE UND das Ergebnis der Umwandlung.
[...]
Daraus schließe ich, daß er solange nach Integer verwandelt, als er von anfang an oder nach führenden Leerzeichen eine Ziffer vorfindet. Sobald dann das erste Nicht-Ziffer-Zeichen auftaucht, bricht er die Verwandlung ab, die aber erfolgreich war, falls überhaupt etwas nach obigen Regeln verwandelt werden konnte.
Genau.
Der Sinn ist, dass man auf diese Weise mehrere Werte aus einem String auslesen kann (was ja, wie gesagt der Hauptzweck dieser Funktionen ist) und die Fehlerabfrage einfach mit "and" kombinieren kann, damit man nicht für jeden einzelnen Wert eine Fehlerbehandlung schreiben muss (solange es einen nur interessiert, ob die Umwandlungen komplett erfolgreich sind oder nicht).
Wenn ich das richtig verstanden habe, nützt mir StrReadInt für meine Zwecke wohl doch nichts, weil ich ja nicht mehrere Werte aus dem betreffenden String auslesen möchte.
Nein, ich dachte, das hätten wir in den vorigen Mails geklärt, dass diese Funktion für deine Zwecke nicht das beste Mittel ist.
Weil Du aber so die Wichtigkeit einer Fehlerbehandlung hervorhebst, habe ich mir nun zum ersten Mal bewußt Gedanken darüber gemacht:
Bisher habe ich beim Programmieren immer all das akribisch auf genaues Funktionieren überprüft, was schon vorhanden war, bevor ich dem Programm weitere Bestandteile hinzugefügt habe.
Zu diesem Zweck habe ich auch immer so wie in dem kleinen Programm "String_nach_Int" Ausgabeanweisungen geschrieben (auch wesentlich komplexere), mit deren Hilfe Fehler schnell gefunden werden konnten.
So ist meine bisherige Erfahrung die, daß all das, was einmal funktioniert, auch in Zukunft immer funktioniert, und wenn es das scheinbar nicht tut, ist der Fehler IMMER in dem neuen Programmbestandteil zu finden, der ja noch nicht so genau geprüft wurde.
Die alten Kontrollen habe ich nach erwiesener Funktionsreinheit immer auch irgendwann, wenn sie wirklich nicht mehr gebraucht wurden, wieder entfernt.
Nun ist allerdings meine "Erfahrung" noch recht klein, und ich lasse mich da gerne eines besseren belehren, falls es gegen diese Vorgehensweise massive Bedenken geben sollte.
Es wäre schön, wenn es immer so ist, aber ich habe es auch schon öfters erlebt, dass beim Ändern eines Teils Fehler in einem anderen Teil aufgetreten sind, z.B. dadurch, dass die Änderungen den "anderen Teil" auf eine Weise benutzen, die ich vorher übersehen hatte (beliebte Fehlerquellen sind dabei Randwerte u.ä., aber manchmal einfach nur unglückliche Kombinationen von Werten, die beim früheren Testen übersehen wurden). Gelegentlich kommt es aber auch vor, dass die Fehler gar nichts mit den neuen Änderungen zu tun haben, und nur zufällig am selben Tag auftreten, an dem man andere Änderungen macht (das wäre dann nur durch Murphy's Law zu erklären).
Fazit: Man kann sich praktisch nie 100%ig darauf verlassen, dass etwas korrekt funktioniert (von Hardware-Fehlern (CPU oder Festplatte) oder Fehlern im Compiler oder den Laufzeitfunktionen mal ganz zu schweigen). Daher ist "defensives Programmieren" meistens empfehlenswert.
Es hängt natürlich immer davon ab, welchen Schaden ein Fehler schlimmstenfalls anrichten kann. Programme, die man nur selbst ein paar mal benutzt, sind weniger kritisch (obwohl auch da natürlich ein Fehlerpotenzial besteht -- wenn du z.B. einen falschen Dateinamen einsetzt und dadurch beim Schreiben der Zahl eine wichtige Datei überschreibst, aber das kann man meistens noch überblicken).
Programme, die übers Netz laufen, sind prinzipiell wesentlich gefährlicher. In diesem Fall hast du die Webseite ja passwortgeschützt, und so lange du das Passwort nur an vertrauenswürdige Personen weitergibt, ist es noch eingegrenzt. Aber wenn es mal öffentlich zugreifbar ist, muss man sich sehr genau über die Sicherheit Gedanken machen. Pascal (so lange man keine Low-Level-Features benutzt) ist zwar schon deutlich sicherer als C (v.a. Pascal-Strings im Vergleich zu C-Strings), aber auch da ist nicht automatisch alles sicher.
An dem Punkt muss man damit rechnen, dass man es nicht nur mit zufälligen Fehlerquellen zu tun hat, sondern dass auf der anderen Seite jemand sitzt, der jede kleinste und unwahrscheinliche Schwachstelle ausnutzen will. Da die "Bösen" meistens kreativer als die "Guten" sind, ist es kaum erfolgversprechend, jeden denkbaren Angriff vorherzusehen und zu verhindern. Daher ist "defensives Programmieren" (oder auch "defense in depth") immer empfehlenswert (d.h., nicht fragen: "Kann ich mir ein Szenario vorstellen, wie hier ein Fehler passieren kann?", sondern: "Kann ich beweisen, dass hier kein Fehler möglich ist, egal, ob vielleicht vorher schon was schiefgelaufen ist?"), weil man damit auch unbekannte und unvorhergesehene Angriffe abfangen kann.
Ein Beispiel: Sonderzeichen in Strings müssen in verschiedenen Situation "geschützt" ("gequotet") werden. Welche Zeichen betroffen sind und wie sie geschützt werden, ist natürlich unterschiedlich. Du kennst vermutlich HTML, wo z.B. "<" als "<" usw. geschrieben werden muss. Wenn man es vergisst, führt das bei "eigenen" Texten meistens nur zur falschen Darstellung. Wenn die Texte aber von Fremden eingegeben werden können, führt es zu Sicherheitslücken, weil sie HTML-Tags einbauen können (s. z.B. http://de.wikipedia.org/wiki/Cross-Site_Scripting). Eine Prozedur, bei deren Erstellung man vielleicht nie an so was gedacht hat und daher mit Quoten nachlässig war, wird vielleicht doch eines Tages in einem Webformular benutzt, und schon hat man den Salat.
Ich hatte mir zum Glück rechtzeitig angewöhnt, u.a. Strings immer zu quoten, es sei denn, es gibt einen bestimmten Grund, es nicht zu tun (statt umgekehrt), und so konnte ich über diverse Angriffe auf meine Web-Programme nur müde lächeln (obwohl ich beim Programmieren noch nichts davon gehört und auch nicht daran gedacht hatte), z.B. eben Formen von Cross-Site-Scripting oder auch Formular-Spam (d.h. bei Web-Formularen, die E-Mails an feste Adressen schicken, baut der Spammer, einen Zeilenumbruch z.B. bei der Absender-Adresse, Subject o.ä. ein, um damit weitere Header zu erzeugen und so Spam an beliebige Adressen zu schicken; dank gequoteter Strings bekam ich zwar eine Fehlermeldung vom Mail-Sever wegen einer sehr merkürdigen Adresse, aber es wurde keine Spam verschickt).
Frank