Warning: Table './usr_web1030_3/variable' is marked as crashed and should be repaired query: SELECT * FROM variable in /var/www/web1030/html/mkernel.de/includes/database.mysql.inc on line 128

Warning: Cannot modify header information - headers already sent by (output started at /var/www/web1030/html/mkernel.de/includes/database.mysql.inc:128) in /var/www/web1030/html/mkernel.de/includes/bootstrap.inc on line 726

Warning: Cannot modify header information - headers already sent by (output started at /var/www/web1030/html/mkernel.de/includes/database.mysql.inc:128) in /var/www/web1030/html/mkernel.de/includes/bootstrap.inc on line 727

Warning: Cannot modify header information - headers already sent by (output started at /var/www/web1030/html/mkernel.de/includes/database.mysql.inc:128) in /var/www/web1030/html/mkernel.de/includes/bootstrap.inc on line 728

Warning: Cannot modify header information - headers already sent by (output started at /var/www/web1030/html/mkernel.de/includes/database.mysql.inc:128) in /var/www/web1030/html/mkernel.de/includes/bootstrap.inc on line 729
[Coding Fundamentals] It was a bad idea anyway... | Drupal

[Coding Fundamentals] It was a bad idea anyway...

  • warning: Cannot modify header information - headers already sent by (output started at /var/www/web1030/html/mkernel.de/includes/database.mysql.inc:128) in /var/www/web1030/html/mkernel.de/includes/common.inc on line 148.
  • user warning: Table './usr_web1030_3/variable' is marked as crashed and should be repaired query: UPDATE variable SET value = 'a:17:{i:0;i:62;i:1;i:61;i:2;i:59;i:3;i:31;i:4;i:30;i:5;i:29;i:6;i:24;i:7;i:21;i:8;i:15;i:9;i:14;i:10;i:11;i:11;i:7;i:12;i:6;i:13;i:5;i:14;i:3;i:15;i:2;i:16;i:1;}' WHERE name = 'menu_masks' in /var/www/web1030/html/mkernel.de/includes/bootstrap.inc on line 609.
  • user warning: Table './usr_web1030_3/variable' is marked as crashed and should be repaired query: UPDATE variable SET value = 'a:0:{}' WHERE name = 'menu_expanded' in /var/www/web1030/html/mkernel.de/includes/bootstrap.inc on line 609.
  • user warning: Table './usr_web1030_3/variable' is marked as crashed and should be repaired query: DELETE FROM variable WHERE name = 'menu_rebuild_needed' in /var/www/web1030/html/mkernel.de/includes/bootstrap.inc on line 634.

Seid Computer und Betriebssysteme multitasking erlauben, kämpfen Programmierer immer und immer wieder mit dem gleichen Problem: dem Speichermanagement. Bisher war ich der Meinung, das die Garbage Collection die Lösung dieses Übels ist. Inzwischen weiß ich: es ist einfach nur das nächste Niveau des Problems.

Ich fange mal ganz von vorne an: In allen Programmierumgebungen, die als systemnah bezeichnet werden, muss der Speicher manuell vom System angefordert und anschließend manuell wieder freigegeben werden. Bei der Umsetzung komplexer Programme entstehen oft nicht nachvollziehbare Fehler: Speicherlecks und Zugriff auf ungültige Speicherbereiche sind die Symtome. Diese Fehler sind bei größeren Programmen fast nicht zu umgehen.

Genau dafür wurde bei interpretierten Programmiersprachen der Garbage Collector eingeführt. Speicher wird hier nur noch alloziert. Aufgeräumt wird automatisch, sobald der Speicher nicht mehr benutzt wird. Damit hat das Übel jedoch nur einen anderen Namen. Garbage Collection ist der Teufel im Schafspelz. Zumindest bei hybriden (systemnah und trotzdem interpretiert) Umgebungen wie dem .NET Framework.

Garbage Collection in der einfachsten Form funktioniert wiefolgt: Der Referenzgraph wird durchlaufen und bei jedem erreichten Objekt wird ein Besuchszähler erhöht. Nach endgültigem Durchlaufen werden alle Objekte freigegeben, deren Besuchszähler immer noch 0 ist. Reine Referenzzähler funktionieren nicht, weil zirkuläre Referenzen dann nicht aufgeräumt werden können.

Doch zum Problem: .NET Unterstützt Aufräumfunktionen, genannt Finalizer. Diese werden in einem separatem Thread aufgerufen, sobald ein Objekt nicht mehr benutzt wird (also keine Referenz mehr darauf zeigt). Damit können die Objekte ihre internen Strukturen aufräumen. Und genau da liegt das Problem. Und bei dem Verständnis einer Referenz. Lokale Variablen definieren eine Referenz nicht für den Kontext, in dem sie gelten, sondern nur bis zu ihrer letzten Verwendung. Nach der Zeile, in der zuletzt auf eine lokale Variable zugegriffen wurde, wird das darüber erreichbare Objekt nicht mehr referenziert.

Einige Objektstrukturen können diesem Problem anheimfallen. Beispiel Bildverarbeitungsbibliothek: Ein Bild wird durch die Klasse Image repräsentiert. Werden die Bilddaten im Rohformat benötigt, können sie durch die Funktion GetImagePointer() abgerufen werden. Wird jetzt ein Bild als lokale Variable geladen und werden anschließend die Rohdaten verarbeitet UND implementiert Image einen Finalizer, so kann das Objekt noch während der Speicherbereich durchlaufen wird, dieser Aufgerufen werden. Das Chaos ist perfekt, da man diesen Fehler nicht wahrnimmt. Die Klasse Bitmap umgeht dieses Problem sehr trickreich durch einen Lock/Unlock-Aufruf. Dadurch ist sichergestellt, das nach dem Durchlaufen der Rohdaten noch einmal auf das Objekt zugegriffen wird.

Fazit: Der Fehler tritt nur auf, wenn ein Objekt A ein Objekt B bereitstellt, B jedoch keine Referenz auf A enthält, A einen Finalizer implementiert, der B wegräumt UND nachdem bereitstellen von B mit A nicht mehr interagiert wird. Genau für diesen Fall gibt es die Funktion GC.KeepAlive, mit der eine Referenz am Leben gehalten werden kann.

in einem Blog von Microsoft wird eingehend dieses Problem beschrieben. Mich hat dieser Fehler beruflich erwischt und eine ganze Weile beschäftigt. Um so mehr bestärkt mich dieses Systemverhalten in meiner Meinung, das Speichermanagement in der Ausbildung zum Informatiker / Programmierer essentiell wichtig ist. Java in der Lehre einzusetzen ist daher problematisch.

Bei der Programmierung sollte man sich also jederzeit darüber bewusst sein, wie mit Speicher verfahren werden soll.

Fazit: Fehlerfreies Speichermanagement ist schon eine schwierige Sache, Fehlerfreie Garbage Collection ist "just the next level".