Dev Diary #4 (Teil 2 von 3) – September-Oktober 2018

Teil 2: Speicherlecks (Memory Leaks)

Wir haben den ersten Teil über „Nicht initialisierte Variablen“ am Montag, den 1. Oktober 2018 gepostet. Dies ist der zweite Teil: „Speicherlecks (Memory Leaks)“.

Es geht hier um relativ technische Themen, aber wir bemühen uns alles so zu umschreiben, dass auch Nicht-Programmierer folgen und einen Überblick erhalten können.
Für die Programmierer unter euch: Uns ist bewusst dass wir hier einiges extrem vereinfachen, also habt bitte Nachsicht mit uns. Die Gilde 3 ist in C++ geschrieben, also setzt bitte eure C++-gefärbten Sonnenbrillen zum Lesen auf.

Das Problem

“Leckender Speicher” klingt nicht nur sehr unangenehm, es handelt sich hierbei tatsächlich um ein sehr häufiges und nerviges Problem. Um dieses (und das nächste) Thema besser zu veranschaulichen müssen wir zuerst diskutieren, wie unser Spiel (und im Allgemeinen jedes Programm) auf Speicher zugreift. Dazu bediene ich mich einer kleinen Metapher:

Stellt euch vor, euer PC ist eine Bibliothek. Die Festplatten und anderen Massenspeicher sind die Regale entlang der Wände und in den Archiven, in denen Bücher voller Daten und Informationen für lange Zeit aufbewahrt werden. Jedes Programm, das ausgeführt wird, ist wie ein Besucher in dieser Bibliothek. Um etwas mit den Informationen bewerkstelligen zu können, müssen die Programme sie zuerst aus den Massenspeichern holen und in ihren privaten Arbeitsbereich befördern. Das ist im Prinzip der Zweck den der Hauptspeicher erfüllt, und wird hier durch ein oder mehrere Lesetische repräsentiert auf denen die Bücher abgelegt werden.

Manche Programme verarbeiten sehr wenig Information, und benötigen daher nur wenig Speicher (in unserem Beispiel ein kleiner Lesetisch in einer Ecke unserer Bibliothek). Andere hingegen bearbeiten massive Datenmengen auf einmal, und besetzen daher mehrere große Lesetische oder gar ganze Säle, auf denen sich dann bergeweise Bücher, Magazine und lose Seiten stapeln.

Als ordentlicher Besucher einer Bibliothek sollte man natürlich ein Buch retournieren, sobald man damit fertig ist. Nicht nur damit jemand anderer es entlehnen kann, sondern auch damit man nicht immer mehr Platz verbraucht, und Tisch um Tisch mit nicht mehr benötigtem Lesestoff befüllt.

Die Auswirkungen

Genau das ist allerdings was passiert, wenn jemand über ein “Speicherleck” spricht. Ein Programm muss immer erst Speicher vom Betriebssystem anfordern, bevor es diesen verwenden kann – etwa um Texturen, Modelle, ausführbare Dateien, Skripte, Audio, oder was auch immer sonst gerade benötigt wird abzulegen. Das Betriebssystem erfüllt diese Anforderungen auch prompt, erwartet allerdings auch, dass das Programm nicht mehr benötigten Speicher wieder freigibt. Geschieht das nicht, wächst der Speicherverbrauch kontinuierlich.

Dank moderner 64 bit Betriebssysteme mit virtuellem Speicher, geschieht es heutzutage im Allgemeinen nicht mehr, dass man wirklich den gesamten Arbeitsspeicher verbraucht. Ein Programm muss schon sehr ausgefallene Verhaltensmuster an den Tag legen, bevor ein Betriebssystem aktiv weitere Speicherallokationen verweigert. Stattdessen wird die Leistung des Programms mit fortschreitender Zeit immer schlechter werden, während der Speicherverbrauch geradezu epische Ausmaße annimmt. Über kurz oder lang wird das Programm unbenutzbar, und der Benutzer wird es beenden.

Die Lösung

In modernem C++ ist es relativ leicht, Speicherlecks zu vermeiden. Der einfache “Ich habe vergessen, Speicher ans Betriebssystem zurückzugeben” Fall den ich erwähnt habe ist nicht, was normalerweise passiert. Viel häufiger wird nicht mehr wirklich benötigter Speicher weiterhin gehalten. Niemand benötigt die Daten darin, aber er wird auch nicht wieder freigegeben.

Dieses Verhalten ist äußerst störend und es ist sehr zeitraubend diese Fehler zu beheben. Es gibt keine guten automatisierten Hilfswerkzeuge um damit fertig zu werden. Stattdessen muss man mit großer Sorgfalt vorgehen, nur Daten behalten, die wirklich benötigt werden, und unnötigen Speicher rechtzeitig freigeben, damit er ans Betriebssystem zurückgehen kann.

Falls ihr mehr Informationen über das Thema “Speicherlecks” haben wollt, ist dieser Wikipedia Artikel ein guter Startpunkt: https://de.wikipedia.org/wiki/Speicherleck

Wir werden diese Story aus dem Entwicklertagebuch bald mit „Speicherfragmentierung“ fortsetzen. Bleibt dran!