Habt ihr schon Urlaubspläne? Ich schon – aber leider viel zu wenig Zeit und viel zu viel Arbeit um mich ausreichend lange und ausreichend weit von meinem Schreibtisch zu entfernen. Deswegen läuft auch mein Blog hier weiterhin ein wenig auf Sparflamme vor sich hin. Aber wenn ihr in der glücklichen Lage seid, ein wenig Urlaub machen zu können: Fahrt doch mal nach Null-Island! Dort soll jede Menge los sein – auch wenn die Realität ein wenig anders aussieht, wie dieses schöne Video demonstriert:
Hat eigentlich jemand tatsächlich schon mal so ein Computerproblem gehabt? Mir ist so etwas glücklicherweise noch nie passiert…
Als Software-Entwickler stößt man ständig auf dieses Problem. Es geht da immer um die Frage, ob man einen Wert „nullable“ oder nicht „nullable“ designed. Grad ganz früher wurde oft auf „nullable values“ verzichtet. Was dann zu solchen Problemen wie oben führen kann. Nachteil von „nullable values“ sind: geringfügig mehr Speicherplatz, bei vielen Operationen muss der Prozessor den einen oder anderen Befehl mehr ausführen, unter Umständen fehleranfälliger und umständlicher beim Schreiben des Codes. Man muss dann nämlich ständig abfragen, ob irgendwas „not null“ ist. Vielleicht hatte der eine oder andere schon mal einen Programmabsturz mit einer kryptischen Fehlermeldung: „Null Pointer Exception“. Da ist der Programmierer nicht davon ausgegangen, dass ein Wert auch NULL sein kann – und dann war der doch NULL.
Ein ähnliches Problem: In einer Personendatenbank konnte man nur das komplette Geburtsdatum angeben. Viele Personen wollten nur das Jahr angeben. Was hat man gemacht: 01.01.19xx. Ziemlich viele Neujahrsbabys waren da in der Datenbank. Man kann dann nicht mehr unterscheiden, ob jemand tatsächlich am 01.01. Geburtstag hat oder ob das nur ein Platzhalter-Wert ist.
In der Programmierung von Computern –also lange bevor der Endnutzer die Sache in die Hand bekommt– tritt dieses Problem eigentlich ständig auf. Manche Programmiersprache erlaubt es einer Variablen keinen Initialwert zuzuweisen, und diese erhält dann automatisch entweder den Wert „0“ oder „Null“, je nach gewählter Sprache. Nicht jede Sprache kennt den symbolischen Wert „Null“, aber wo vorhanden, ist er verschieden vom Zahlenwert 0. Viele der aufzurufenden Funktionen (und davon nutzt man als Programmierer jede Menge) unterscheiden nicht zwischen diesen beiden Wertevarianten, und schon wird bei Bedarf an Zahlen eine 0 interpetiert, wo eigentlich „Null“ vorhanden war. Da, wo Programmiersprachen diese Typenunterschiede (Zahlenwert oder symbolische Null) nicht kontrollieren oder auch nicht auf das Setzen bestimmter Anfangswerte achten, muss der Programmierer dies alles bedenken. Sollte er, sonst entstehen Fehler, wie auch in #1 oben beschrieben.
Diese Wertefehler oder Initialisierungsfehler können an vielen Stellen auftreten, eben auch im Zusammenhang mit Datenbanken oder bei der Werteingabe in Bildschirmformularen. Gerade das Problem mit dem Null-Island tritt auf, wenn man seine eigene Position mit Longitude und Latitude angeben soll, dies aber noch nicht geschehen ist und die Werte somit eigentlich „undefined“ oder „Null“ sind. Von Programmen werden diese Werte der Einfachheit halber als „0“ angenommen.
Ein Beispiel dafür ist die Webseite zur Bestimmung von Positionen bestimmter Himmelskörper Heavens-Above. Man kann oben rechts seine eigene Position angeben, bzw. im entsprechenden Menüpunkt. Ausgewertet wird diese Information u.A. auch in der Aufrufstatistik ganz unten im Menü. Auf der Weltkarte ist der Nullmeridian erkennbar, ausgelöst durch alle Nutzer mit (0,0)-Aufruf. Warum der Äquator bzw. Breitgrad 0 nicht erkennbar ist, erklärt sich mir nicht.
„… ausgelöst durch Nutzer mit (0,La)-Aufruf, wenn 0 die Länge und La die Breite/Latitude ist.“
So sollte es heißen. Der umgedrehte Aufruf mit (Lo,0) scheint nicht so häufig vorzukommen, daher keine Breite 0.
AlsBegründung wohl falsch, Hannes, da in jeder mir bekannten Sprache explizit ein NullWert einem pointer zugewiesen werden kann und das den Programmierern auch bekannt sein dürfte. Die dürften allerdings davon ausgegangen sein, daß vor der (NichtNull annehmenden) Verwendung schon irgendwer irgendwo irgendwann einen sinnvollen Wert zugewiesen haben wird.
Generell wird in solchen Fällen bei ordentlicher Programmierung ein Wert (eine Bitkombination) als ‚hier steht noch nichts‘-vertretend ausgeguckt, und zwar nicht nur bei den reellen Zahlen und nicht erst seit 1985 (IE³ NaN). Ulkiger- und typischerweise übrigens 0 oder HighBitSet, weil in diesen Fällen der Test derart simpel ist, daß er auch schon in der Assemblervariante gemacht wurde bzw vom Compiler minimalistisch umgesetzt werden kann.
So ist das völliger Blödsinn, Braunschweiger, kein Initialwert ist gleichbedeutend zu nie ein Wert (einer ist immer der erste). Du meinst sicherlich ‚im Zuge der Deklaration‘, doch das ist nur eine SchreibfaulheitsHilfe – die alte Kombination deklarieren+initialisieren ist überall implementiert (zugegeben, Deklaration ist manches Mal optional) und genausogut automatisch verifizierbar.
Selbstverständlich, Florian, in letzter Zeit aber nur noch in wildwuchernden JavaTrümmern – dafür allerdings mit derart gräßlich zu interpretierenden Fehlerlogs, daß der Entwickler / WartungsGuru anscheinend erst mal einen oder mehrere Tage schwere Meditation einlegen muß ;‑)
@Rolak:
Heutzutage ist es ja so, dass man eigentlich fast nur mehr mit Variablen zu tun hat, die eigentlich Pointer sind und somit nullable sein können. Strings, Objekte, andere Nullable-Datentypen. In vielen Anwendungen braucht man kaum mehr „herkömmliche“ Variablen wie ints oder floats 😉 (Ich spreche von Web-Anwendungen oder datenbanklastigen Anwendungen.) Und wenn man dann fast nur mehr nullable Datentypen hat, muss man schon überlegen, wo baue ich eine Prüfung auf NULL ein und wo nicht. Mittlerweilen ist es zwar deutlich einfacher geworden. Der Zeitverlust spielt in den allermeisten Fällen keine Rolle. Manche Sprachen haben Erweiterungen, die den Code kürzer und lesbarer machen (C#: null-coalescing, null-propagation, …).
Vor 10-12 Jahren habe ich ziemlich häufig Null-Pointer-Exceptions korrigiert. Meistens ging es um Strings, die im normalen Programmablauf nie NULL waren (wenn dann ein leerer String). Irgendwann später – durch einen vorgelagerten Fehler – ist so ein String plötzlich doch NULL -> Exception.
Datenbankmäßig ist das das Standardverhalten des alternden Platzhirsches Oracle. Die haben diese Verletzung der relationalen Algebra verursacht und …
In C wird gern NULL als 0 angenommen, aber das steht nicht in der Norm. Es gibt durchaus Compiler, die NULL nicht als Bit-Pattern der Form 000000 implementieren.
Einer des besten Fehler in dem Zusammenhang hatte ich mal mit einer HW und einem kleinen Prozessor. Das Ding lief fehlerfrei über Jahre aber plötzlich nach einem HW update einiger Komponenten gab es sporadische Ausfälle. Unsere Abteilung hat tagelang getestet um den Fehler zu finden. Zufälligerweise haben wir dann herausgefunden, dass für die Programmierung im Zuge der HW-Umstellung das Tool gewechselt wurde. Das neue Tool löschte vor dem programmieren NICHT den gesamten Speicher und so konnte es passieren, dass die eine nicht initialisierte Variable NICHT den Wert Null hatte und es daraufhin manchmal zu einem Absturz kam. Quasi ein NICHT-NULL Problem 🙂
Die Programmierer spielen seit jeher ein Spiel ohne Grenzen:
– Der eine definiert Konventionen und hält sich daran.
– Der nächste kommt auf die Idee, dass man auch alles ganz anders auffassen kann
– Noch ein anderer sagt, dass Standards ganz übel sind und verhält sich entsprechend
…
…
…
Leute mit gesundem Menschenverstand sind unter Betriebssystementwicklern nicht oft anzutreffen. Zu dieser raren Spezies gehört David Bailey, der Entwickler von DBOS. Dessen Idee Bitmuster so zu missbrauchen, dass den geplagten Softwareentwicklern das Leben erleichtert und die Freizeit in vielen Fällen ungemein verlängert wurde, war zwar auch nicht standardkonform, aber ungemein nützlich. Einen der befürchteten Fehlalarme habe ich nie erlebt:
Checking for undefined variables (/UNDEF)
/UNDEF (which implies /CHECK) causes FTN77 to plant code to check that a variable or array element used in the circumstances described below has been previously given a value.
All local static variables are predefined to an undefined value. This value has HEX 80 in every byte. Routines compiled with /CHECK also clear their dynamic variables to this value on entry to the routine. This value is treated as undefined by the symbolic debugger.
Aus: http://www.silverfrost.com/manuals/77userguide.pdf
Wer zum Teufel ist David Bailey?
die vm’s sind alle stack basiert. regiester proz ist ok macht halt so weiter.
helft mal den menschen war ja vor 20 jahren einfacher einen kreis zu zeichnen wie heute.
@tomtoo:
Don’t drink and post …