-
Die
vorliegende Erfindung betrifft ein Verfahren und Computerprogrammprodukt
zur Detektion von Speicherlecks, die durch ein Programm erzeugt werden,
welches auf einem Computer abläuft,
wobei während
eines Programmlaufes eine Speicherleck-Liste erstellt wird.
-
Als
Speicherleck (engl. Memory-Leak) bezeichnet man einen allozierten
Speicherbereich, insbesondere Speicherblock, der nach seiner Verwendung
von einem Programm, welches auf einem Computer abläuft, nicht
mehr freigegeben wird. Dieser Speicherbereich, insbesondere Speicherblock,
ist dann für
die gesamte Laufzeit des Programms nicht mehr für das Programm oder andere
Zwecke (andere Programme oder Betriebssystemanforderungen) verwendbar
und es kann vorkommen, insbesondere wenn solche Speicherlecks mehrfach
auftreten, dass der noch zur Verfügung stehende Speicher knapp wird.
-
Hinzu
kann kommen, dass durch eine Fragmentierung des Hauptspeichers durch
nicht freigegebene Speicherbereiche größere zusammenhängende Speicherblöcke (z.B.
größer 100
MB) vom System nicht mehr wirksam anforderbar sind. Das System wird
belastet und kann nach und nach instabil werden.
-
Programmierern
passieren in maschinennahen Sprachen (wie C/C++) solche Speichermanagementfehler
relativ häufig.
Es wird wegen der ständig
zunehmenden Komplexität
vergessen, den reservierten Speicherbereich/Speicherblock zum richtigen
Zeitpunkt wieder freizugeben. Detaillierte Ausführungen zu den Grundlagen zu
Speicherlecks sind z.B. in den Dokumenten US 2005/0235127 A1 und
US 2004/0078540 A1 offenbart.
-
Der
Zeitpunkt, ab dem ein Speicherbereich/Speicherblock durch ein Programm
nicht mehr verwendet wird, lässt
sich mit Software-Automatismen praktisch nicht feststellen. Es gibt
derzeit kein Werkzeug, das dem Entwickler eine 100%-ige Erkennung
solcher Fälle
ermöglicht.
Der Entwickler kann zwar wie unten beschrieben nach Ende der Ausführung seines
Programms alle aufgetretenen Speicherlecks aufgelistet bekommen,
aber zur Behebung des zugrunde liegenden Programmierfehlers würde er eine
Zuordnung zu der konkreten Situation während der Programmausführung, in
welcher der fragliche Speicherbereich/Speicherblock alloziert wird,
benötigen.
-
Die
am Markt befindlichen Werkzeuge, wie das Programm FINDLEAK der Firma
cjt Systemsoftware AG und die in den Schriften US 2005/0235127 A1
und US 2004/0078540 A1 aufgezeigten Verfahren geben dem Entwickler
anhand von heuristischen Methoden einen Hinweis auf potentielle
Speicherlecks. Nachteilig ist, dass diese der Entwickler immer noch einzeln
verifizieren muss. D. h. erst beim Programm-Ende ist klar, dass
alle nicht freigegebenen Speicherbereiche/Speicherblöcke Speicherlecks sind.
Eine Möglichkeit,
die bestätigten
Speicherlecks am Programm-Ende den heuristischen Hinweisen zuzuordnen
und damit im laufenden Programm die näheren Umstände des Speicherlecks nachzuvollziehen,
ist nicht gegeben.
-
Zur
Reduzierung der beschriebenen Probleme bietet Microsoft Visual Studio
dem Entwickler mit der CRT (C Runtime Library) und der MFC (Microsoft Foundation
Classes) eine Möglichkeit,
mögliche Speicherlecks
nach dem Ablaufen eines Programms zu benennen. Die MFC protokolliert
dazu alle Speicheranforderungen und -freigaben und gibt nach Ablaufen
des Programms übrig
gebliebenen Einträge als
Textausgaben, z.B. in einem Debug-Ausgabefenster als Speicherleck-Liste
bzw. Speicherleck-Dump aus. Der Programmierer kann also durch diese
von Microsoft oder ggf. anderen Anbietern gegebene Möglichkeit
eine Speicherleck-Liste erstellen, in denen alle am Ende eines Programmlaufs
allozierten aber nicht mehr freigegebenen Speicherbereiche/Speicherblöcke aufgelistet
sind, ggfs zusammen mit anderen Informationen.
-
Eine
im Visual Studio mit Wizard-Unterstützung erstellte MFC-Anwendung
protokolliert und meldet die Speicheranforderungen automatisch.
In selbst erstellten Konfigurationen kann der Entwickler die Protokollierung
mit der Methode _CrtSetDbgFlag einschalten.
-
Die
Informationen, welche die MFC zu diesem Zeitpunkt noch bereitstellen
kann, sind rudimentär.
Nach Programmende sind keine Klassennamen oder Call-Stacks mehr
verfügbar
und die Mitprotokollierung dieser Informationen zur Laufzeit ist
sehr speicheraufwendig. Zum Teil wird der Dateiname und die Zeilennummer
angegeben in der das Objekt alloziert wird, aber häufig ist
diese Angabe nicht gegeben, da der Name der Datei, aus der der Aufruf kommt,
nur dann bekannt ist, wenn er den protokollierenden Speichermanagement-Routinen
gezielt übergeben
wurde, was oftmals nicht vorgenommen wird. Hierfür werden Präprozessor-Makros eingesetzt,
aber diese können
leicht außer
Funktion gesetzt oder erst gar nicht verwendet werden. Dadurch sind
in der Regel nur rund 50% der Speicherlecks mit Dateinamen versehen.
-
Dateiname
und Zeilennummer weisen zwar genau auf das Objekt hin, welches alloziert
wurde, aber in den meisten Fällen
nützt das
dem Entwickler nichts, denn der Allokations-Code ist in der Regel einwandfrei
und der Programmierer muss herausfinden, warum das Objekt alloziert
und nicht wieder freigegeben wird und insbesondere an welcher Stelle
in einem Programm dieser Fehler aufgetreten ist.
-
Die
Speicheradresse beinhaltet kaum verwertbare Information, weil diese
bei jedem Programmlauf anders lautet und nach Ablauf des Programms
keinen Hinweis auf den Kontext der Allokation liefert.
-
Die
Speicherblockgröße gibt
dem Entwickler unter besonderen Umständen einen Hinweis auf das Objekt,
hat aber in der Regel keine Aussagekraft und wird daher in Standardverfahren
nicht verwendet. Zudem kommt es hier auf die Erfahrung des Entwicklers an.
-
Der
Kern eines von Microsoft vorgeschlagenen Verfahrens zur Eliminierung
von Speicherlecks ist die Einführung
einer fortlaufenden Allokationsnummer. Sie gibt an, die wievielte
Speicheranforderung während
des Programmlaufs zu dem Speicherleck geführt hat.
-
Zusammen
mit der genannten Protokollierungs-Option gibt es z.B. die Funktion (_CrtSetBreakAlloc),
mit deren Hilfe der Entwickler die Ausführung des Programms anhalten
kann, wenn eine der Funktion übergebene
Allokationsnummer erreicht wird. Setzt der Entwickler hier die beim
letzten Speicherleck-Dump gemeldete Nummer ein, so hält das Programm
beim nächsten
Lauf genau an der Stelle an, wenn das „verlorene" Objekt alloziert wird. Diese Zuordnung
des festgestellten Speicherlecks zu der konkreten Laufzeit-Situation
während
der Allokation gibt dem Entwickler den entscheidenden Hinweis zur
Behebung des zugrunde liegenden Programmierfehlers.
-
In
der Praxis großer
GUI-intensiver Anwendungen treten aber bei den meisten Speicherlecks Allokationsnummern
im 6- bis 8-stelligen Bereich auf. Aufgrund der starken Vernetzung
dieser Anwendungen mit dem autarken GUI- und Task-Management des Betriebssystems,
ist die Verknüpfung
zwischen Objektallokation und Allokationsnummer nicht mehr deterministisch.
Schon geringe Laufzeitunterschiede zwischen zwei als identisch beabsichtigten
Programmläufen
führen
zu unvorhersagbaren Verschiebungen bei den Allokationsnummern desselben
Objektes in den verschiedenen Durchläufen.
-
Dies
kann z.B. daran liegen, dass neben den Allokationen von Speicherbereichen
durch das zu untersuchende Programm auch Allokationen von Speicherbereichen
durch das Betriebsystem oder andere parallel laufende Programme
erfolgen. Somit durchmischen sich die Speicherallokationen und ggf. Freigaben
des eigentlichen zu untersuchenden Programms mit denjenigen Allokationen
und ggfs. Freigaben anderer Programme bzw. des Betriebssystems,
welches eindeutige Rückschlüsse auf
die Ursache einer Allokation und insbesondere einer fehlenden Freigabe
für einen
Programmierer nahezu unmöglich
macht.
-
Das
von Microsoft vorgeschlagene Verfahren erfährt hier seine natürliche Grenze:
Wegen der Nichtdeterminiertheit verliert die Allokationsnummer ihre
Aussagekraft und die Suche nach dem zugrunde liegenden Programmierfehler
für das
Speicherleck wird damit unmöglich.
-
Aufgabe
der Erfindung ist es, ein Verfahren und Computerprogrammprodukt
bereitzustellen, mittels denen mit Sicherheit oder zumindest einer
erhöhten
Wahrscheinlichkeit Speicherlecks, die durch Fehlprogrammierung in
einem ablaufenden Programm entstehen, detektiert werden können und auch
eine Zuweisung von Programmierbereichen, welche für die Entstehung
von Speicherlecks verantwortlich sind, zu entsprechenden Speicherlecks möglich ist.
-
Weiterhin
ist es Aufgabe, die aufgezeigten Nachteile des Standes der Technik
zu überwinden und
trotz der Nichtdeterminiertheit, insbesondere der Allokationsnummern,
die Ursachen der Speicherlecks zu erkennen, d.h. einen Hinweis auf
die Programmstelle in einem laufenden Programm zu erhalten, durch
die das Speicherleck entsteht.
-
Gelöst wird
die Aufgabe durch ein Verfahren, bzw. ein Computerprogrammprodukt
zur Durchführung
des Verfahrens mittels eines Computers, bei dem während eines
Programmlaufes bei jeder Allokation eines Speicherbereiches wenigstens
eine Information über
die erfolgte Allokation in eine Allokationsliste eingetragen wird
und überprüft wird,
ob die Allokationsliste ein für
ein oder mehrere Speicherlecks typisches gespeichertes Vergleichs-Muster
von Informationen aufweist, wobei nach einem Auffinden eines gespeicherten
Musters der Programmlauf unterbrochen wird oder ein so detektiertes
Speicherleck dem Bereich des ablaufenden Programms zugeordnet wird,
durch dessen Abarbeitung der letzte Eintrag in die Allokationsliste
erfolgte.
-
Wesentlicher
Kerngedanke der Erfindung ist es, dass wenigstens ein Vergleichsmuster
vorliegt mit einer Abfolge von bestimmten Informationen, die bekannt
ist für
ein Speicherleck, welches durch ein ablaufendes Programm entsteht
und dessen Ort der Entstehung im Programm ermittelt werden soll,
um so den Fehler, der zur Erzeugung des Speicherlecks führt, eliminieren
zu können.
-
Es
wird somit gemäß der Erfindung
während der
Laufzeit des Programms danach gesucht, ob in der Allokationsliste,
die während
der Laufzeit mit jeder neuen Allokation von Speicher mit wenigstens
einer Information hierüber
ergänzt
wird, eine Informationsabfolge entstanden ist, die dem gespeicherten Muster
entspricht. Wird ein solches gespeichertes Vergleichs-Muster in
der Allokationsliste gefunden, so deutet dies auf das Entstehen
des gesuchten Speicherlecks im Programm hin, insbesondere wobei der
Zeitpunkt des Entstehens gegeben ist durch den Zeitpunkt des Einschreibens
der letzen Allokationsinformation in die Allokationsliste. So ist
es für
eine genaue zeitliche Auflösung
des Entstehens und der Lokalisierung im Programmcode vorteilhaft,
wenn die Suche nach einem gespeicherten Vergleichsmuster nach jedem
Einschreiben einer Information in die Allokationsliste neu gestartet
wird.
-
Da
diese Suche während
der Laufzeit des Programms erfolgt, besteht die Möglichkeit
das Programm sofort anzuhalten, wenn das gesuchte Vergleichsmuster
gefunden wurde. Hierdurch erhält
der Programmieren einen Hinweis auf den Ort des Entstehens des Speicherlecks
im Programmcode und kann den Fehler beheben.
-
Alternativ
kann es auch vorgesehen sein, dass das Programm nicht angehalten
wird, jedoch ein so detektiertes Speicherleck dem Bereich des ablaufenden
Programms zugeordnet wird, durch dessen Abarbeitung der letzte Eintrag
in die Allokationsliste erfolgte. Z.B. kann so eine Zuordnungstabelle erzeugt
werden und der Programmierer kann zu einem späteren Zeitpunkt durch die Zuordnungshinweise
die den Fehler erzeugenden Programmteile identifizieren.
-
Gegenüber dem
bekannten Stand der Technik bietet somit die Erfindung den Vorteil,
dass neben einer Feststellung dass ein Speicherleck entstanden ist
auch die Möglichkeit
gegeben wird, den Fehler erzeugenden Programmcode im Programm zu
lokalisieren.
-
Wesentlich
für die
Erfindung ist es somit, dass neben dem zu untersuchenden Programm
auch eine Programmroutine durch einen Computer abgearbeitet wird,
die die Allokation von Speicher protokolliert und dafür Sorge
trägt,
dass für
die Allokation typische und/oder bedeutsame Informationen in die Allokationsliste
immer dann eingetragen werden, wenn eine neue Allokation stattfindet.
-
Eine
solche Routine, kann z.B. in einer Softwarebibliothek vorgesehen
sein, z.B. die zum Programm hinzugelinkt wird, so dass mit jeder
Allokation die Routine aufgerufen wird.
-
Eine
typische, wichtige oder bedeutsame Informationen über eine
durchgeführte
Allokation kann z.B. die Länge
eines allozierten Speicherbereichs bilden. So kann es vorgesehen
sein, dass die Allokationsliste durch eine Liste gebildet wird,
in die nacheinander immer wieder Zahlen eingetragen werden, die
der Länge
des jeweils zuletzt allozierten Speicherbereichs entsprechen. Durch
den Ort der Zahlen in der Liste wird dabei automatisch auch identifiziert,
welchen relativen Abstand die jeweils allozierten Speicherblöcke voneinander
haben.
-
Das
wenigstens eine Vergleichsmuster, welches gespeichert ist, um für einen
Vergleich herangezogen zu werden, kann dabei auf jegliche Art und Weise
entstanden sein. Z.B. kann es eine Bibliothek mit typischen Muster
geben, die z.B. durch typische Fehlprogrammierung entstehen.
-
Es
kann in besonders bevorzugten Ausführungen des erfindungsgemäßen Verfahrens
auch vorgesehen sein, dass vor einem Programmlauf zum Lokalisieren
eines ein Speicherleck erzeugenden Programmcodes vorherigen Programmläufe durchgeführt werden,
um einen Gesamtüberblick
zu erhalten, was für
Speicherlecks das zu untersuchende Programm insgesamt erzeugt und
welche Muster für die
Speicherlecks typisch sind, um dann später zur Laufzeit eines separaten
Programmlaufes die Lokalisierung durchzuführen. Hierbei kann auf Programme zurückgegriffen
werden, die im Stand der Technik bekannt sind, Speicherlecklisten
zu erzeugen.
-
So
kann es in einer Ausführung
vorgesehen sein, dass zur Erzeugung wenigstens eines Vergleichs-Musters
insbesondere bei einem vorherigen Programmlauf eine Speicherleckliste
erzeugt wird, die nach dem Programmlauf Informationen umfasst über alle
bei dem Programmlauf erzeugten Speicherlecks, wobei die Speicherleckliste
oder eine daraus erstellte Datei nach Informationen durchsucht wird, die
für Speicherlecks
typisch sind und wobei diese Informationen oder daraus abgeleitete
Daten als wenigstens ein Muster gespeichert werden.
-
So
können
in solchen Speicherlecklisten z.B. wie eingangs genannt absolute
Allokationsnummern und Speicherbereichslängen niedergeschrieben sein.
Es besteht somit die Möglichkeit
aus einer solchen Speicherleckliste Vergleichs-Muster zu generieren,
z.B. dadurch, dass eine Speicherleckliste nach dem Vorkommen von
Längenangaben
und/oder Allokationsnummern durchsucht wird. Eine oder auch mehrere
aufeinander folgende Längenangaben
können
ein Vergleichsmuster bilden, welches gespeichert wird für eine spätere Lokalisierung,
z.B. durch Speicherung der Abfolge oder einer Teilabfolge der in der
Speicherleckliste aufgelisteten Längenangaben.
-
Problematisch
ist es, dass ggfs. durch Einflüsse
des Betriebssystems oder anderer Programme eine absolute Abfolge
von Längenangaben
in einer solchen Speicherleckliste nicht immer gleich ist, so dass
nicht zwingend bei einem späteren
Programmlauf ein gespeichertes Muster gefunden wird.
-
In
einer anderen bevorzugten Ausführung kann
es daher vorgesehen sein, dass zur Erzeugung wenigstens eines Vergleichs-Musters
bei wenigstens zwei, insbesondere vorherigen Programmläufen je eine
Speicherleckliste erzeugt wird, die nach dem jeweiligen Programmlauf
Informationen umfasst über alle
bei dem jeweiligen Programmlauf erzeugten Speicherlecks, wobei die
wenigstens zwei Speicherlecklisten oder daraus jeweils erstellte
Dateien auf zumindest bereichsweise übereinstimmende Informationen
durchsucht werden, wobei die zumindest bereichsweise übereinstimmenden
Informationen oder daraus abgeleitete Daten als wenigstens ein Muster
gespeichert werden, insbesondere wobei jeder zusammenhängende Bereich
von übereinstimmenden
Informationen ein Muster bildet.
-
Es
wird somit wenigstens zweimalig ein Programmlauf eines auf Programmierfehler
zu untersuchenden Programms durchgeführt, wobei bei jedem Programmlauf
eine Speicherleck-Liste erstellt wird, z.B. mittels eines vorbeschriebenen
Verfahrens, welches von Microsoft bekannt ist und angeboten wird oder
mittels eines anderen Verfahrens, welches eine solche Speicherleck-Liste
bereitstellt.
-
Erfindungsgemäß ist es
sodann vorgesehen, dass die wenigstens zwei bei den jeweiligen Programmläufen erstellten
Speicherleck-Listen oder daraus erstellte Dateien auf übereinstimmende
Muster durchsucht werden. Hierbei kann das Auftreten eines in beiden
Speicherleck-Listen/Dateien gemeinsamen Musters auf ein erzeugtes
Speicherleck hinweisen, insbesondere bei dem eine erweiterte Determiniertheit über das
Muster hergestellt und damit die Auffindung des zugrunde liegenden
Programmierfehlers ermöglicht
werden kann.
-
Wesentlicher
Kerngedanke dieser Ausführung
ist es, dass durch die Suche nach übereinstimmenden Mustern in
den wenigstens zwei Speicherleck-Listen oder jeweils daraus erstellten
Daten die Wahrscheinlichkeit gesteigert wird, dass durch ein detektiertes
Muster, welches auf ein Speicherleck hindeutet, ein solches Speicherleck
identifiziert wird, welches auf den Lauf des zu untersuchenden Programms
und nicht auf andere Umstände
zurückzuführen ist.
-
Wie
eingangs erwähnt,
ist es ein Problem bei der Auswertung einer einzelnen Speicherleck-Liste, dass
neben Speicherlecks, die durch das zu untersuchende Programm entstehen
auch solche Speicherlecks gelistet werden, die durch Einflüsse von
parallel laufenden Programmen oder Betriebssystemroutinen entstehen
können,
die sich also mehr oder weniger zufällig, d.h. nicht deterministisch
in die Abfolge der detektierten Speicherleck einreihen und den Programmierer
nicht interessierten.
-
Da
die Wahrscheinlichkeit eher gering ist, dass „zufällig" bei wenigstens einem weiteren Programmlauf
ein Speicherleck, insbesondere an gleicher Stelle und mit gleicher
Länge,
wiederum durch ein anderes Programm/Betriebssystem entsteht und diejenigen
Speicherlecks, die definitiv auf das zu untersuchende Programm zurückgehen,
selbst bei verschiedenen/mehrfachen Programmläufen wenigstens teilweise identische
Informationen in einer Speicherleckliste erzeugen, wie z.B. die
Länge des
Lecks und den Ort, bzw. den Abstand zu einem vorher erzeugten Leck,
darf bei gleichen auftretenden Informationen in den wenigstens zwei
Speicherlecklisten oder daraus erstellten Daten darauf geschlossen werden,
dass ein hierdurch identifiziertes Speicherleck auf eine Fehlprogrammierung
des zu untersuchenden Programms zurückgeht und nicht auf ein parallel
laufende anderes Programm oder das Betriebssystem.
-
Um
die übereinstimmenden
Informationen in den jeweiligen Speicherleck-Listen zu finden kann
es vorgesehen sein, ein Verfahren zu einer Mustersuche auf die jeweiligen
Listen anzuwenden oder auf Dateien, welche zumindest teilweise Informationen der
jeweiligen Speicherlecklisten umfassen, ggfs. auch neu generierte
Informationen.
-
Für die Mustersuche
können
somit bekannte Verfahren eingesetzt werden, die nicht den eigentlichen
Gegenstand der Erfindung bilden. Beispielsweise können hier
dem Fachmann geläufige
Verfahren, wie der „LCS(Longest
Common Subsequence)"-Algorithmus oder
der „Diff"-Algorithmus eingesetzt
werden, welche in der Lage sind, Muster zu erkennen, die z.B. auf
der Erkennung der längsten
zusammenhängenden
Zeichenfolge basieren. Auch kann das dem Fachmann bekannte Softwareprogramm „beyond
compare" eingesetzt
werden.
-
Derartige
Verfahren zur Mustererkennung können
in einem separaten Programm implementiert sein, welches die Informationen
aus den Speicherlecklisten oder den daraus erstellten Dateien einlesen
oder bereits in einem Programm implementiert sein, welches das erfindungsgemäße Verfahren komplett
durchführt.
-
So
kann ein solches Komplettprogramm z.B. vom Entwickler auf einem
Computer gestartet werden, wobei als ein Übergabeparameter z.B. der Name
des zu untersuchenden Programms übergeben
werden kann oder der Programmcode direkt. Das Programm zur Durchführung des
erfindungsgemäßen Verfahren
kann dann die wenigstens zweimalige Ausführung vornehmen und die Listen
oder Dateien aus den Listen erstellen und z.B. besonders bevorzugt
sofort die Mustererkennung vornehmen.
-
Um
die Suche nach übereinstimmenden Mustern
zu erleichtern, kann es in einer Ausführung der Erfindung vorgesehen
sein, dass die Länge
der allozierten und nicht mehr freigegebenen Speicherblöcke und/oder
der Abstand eines Speicherlecks zu einem vorherigen untersucht wird.
Hierzu kann es auch vorgesehen sein, diese Informationen aus den Speicherlecklisten
zu extrahieren und insbesondere vor einer Musteruntersuchung in
jeweils separate Dateien zu schreiben.
-
Wesentlicher
Gedanke hierbei ist es, das Speicherlecks, die durch ein zu untersuchendes
Programm erzeugt werden, voraussichtlich immer dieselbe Länge haben
und somit zum Programm zugeordnet werden können. Da dies ggfs. auch bei
periodisch aufgerufenen Betriebssystemroutinen auftreten kann, kann
es gemäß einer
Weiterbildung vorgesehen sein auch den Ort eines Speicherlecks auszuwerten, bzw.
da dieser zu eingangs erwähnt,
selbst bei zwei identischen Programmläufen abweichend sein kann,
den Abstand zwischen zwei Speicherlecks auszuwerten, da dieser konstant
bleibt, bei zwei identischen Programmläufen.
-
Somit
kann es vorteilhaft sein, bei der Mustersuche maßgeblich auf den Abstand und
die Länge von
Speicherlecks abzustellen. Hierbei kann es vorgesehen sein, dass
bei der Mustersuche solche Einträge
nicht berücksichtigt
werden, bei denen ein Abstand einen vorgegebenen Grenzwert übersteigt, z.B.
bei denen der Abstand größer ist
als 100.
-
Um
diese Suche zu vereinfachen, kann es weiterhin in einer Ausführung der
Erfindung vorgesehen sein, zunächst
bestimmte Informationen aus einer jeweiligen Speicherleck-Liste
in eine jeweilige separate Datei einzuschreiben und hierbei ggfs.
aus den bestehenden Informationen neue zu generieren. Bei den Informationen,
die aus der jeweiligen Speicherleck-Liste extrahiert werden, kann
es sich somit beispielsweise wenigstens um die Abstände und Längen von
Speicherlecks handeln, wobei die Abstände z.B. generiert bzw. ermittelt
werden können aus
der Differenz der Allokationsnummern, die bei der Erstellung der
Speicherlecklisten durch die bekannten Verfahren in die Listen eingeschrieben
werden.
-
Die
Suche nach solchen vorgenannten Mustern vereinfacht sich somit,
wenn diese separaten Dateien untersucht werden, welche hauptsächlich solche
Informationen umfassen, die ggfs. erst gebildet werden, wie z.B.
die Differenz der Allokationsnummern, so dass dann in vereinfachter
Weise wiederum die Mustererkennungsverfahren der vorgenannten Art
eingesetzt werden können,
die z.B. größte übereinstimmende
Textbereiche erkennen und somit nicht extra auf die Suche nach Abständen und Längen von
Speicherlecks oder auf sonstige vorgegebene Muster ausgelegt sein
müssen.
-
Es
kann somit auf Standardverfahren zurückgegriffen werden. Die Erstellung
solcher zwischengeordneter Dateien ist jedoch nicht zwingend notwenig
für das
Verfahren, die übereinstimmenden Muster
können
auch direkt in den Speicherleck-Listen gesucht werden, ggfs. durch
hierfür
angepasste Programme.
-
Gemäß einer
Ausführung
des Verfahrens werden als Muster z.B. wiederkehrende Zahlenpaare aus
Leckabstand und Lecklänge
verwendet, ggfs mit zusätzlichen Informationen,
wo in einer Datei oder originären
Speicherleck-Liste die Zahlenpaare gefunden wurden. Diese Ortsangaben
können
durch Zeilennummern gegeben sein.
-
Werden
bei der Durchführung
des erfindungsgemäßen Verfahrens übereinstimmende
Informationen gefunden, so ist es vorteilhaft diese als Vergleichs-Muster jeweils abzuspeichern
für einen
späteren
Zugriff, bei der Lokalisation.
-
Eine
Speicherung von Vergleichsmustern, unabhängig davon woher diese stammen,
kann dabei in einem Speicherbereich des Computers erfolgen, auf
dem das zu untersuchenden Programm und/oder ein Programm zur Durchführung des
Verfahrens abläuft.
Z.B. kann die Speicherung in der Registry des Computers erfolgen.
Hierbei ist es vorteilhaft, wenn nur solche Muster für einen
späteren
Vergleich gespeichert werden, die mehr als ein Speicherleck umfassen,
da mit der Anzahl aufeinander folgender Speicherlecks die Wahrscheinlichkeit steigt,
dass diese Speicherlecks durch das zu untersuchende Programm erzeugt
wurden.
-
Durch
die so oder auf andere Art gewonnenen Vergleichsmuster stehen einem
Programmierer bessere Möglichkeiten
zur Verfügung
Speicherlecks zu identifizieren, bei denen eine Zuweisung zu den Programmierbereichen,
die für
das Speicherleck verantwortlich sind, möglich ist.
-
Mit
den ggfs. vorher gewonnenen Vergleichsmustern kann nun für wenigstens
ein Vergleichsmuster, bevorzugt für jedes einzelne Vergleichsmuster
je ein Programmlauf durchgeführt
werden, während
dem zeitgleich eine zuvor beschriebene Allokationsliste erstellt
wird und in dieser nach dem jeweiligen Vergleichs-Muster nach jedem
neuen Eintrag gesucht wird.
-
Ggfs.
kann es vorkommen, dass ein gespeichertes Muster in der Allokationsliste
bei einem Programmlauf gefunden wird, aber tatsächlich kein Speicherleck entstanden
ist. So kann es vorgesehen sein, dass nach dem Finden eines Musters
nur dann auf die Existenz eines tatsächlichen Speicherlecks geschlossen
wird, wenn tatsächlich
gleichzeitig in eine parallel geführte Speicherleckliste auch
ein Speicherleck eingetragen wurde.
-
Wird
eine Übereinstimmung,
insbesondere bei gleichzeitiger Eintragung eines Speicherlecks in der
Speicherleckliste gefunden, so kann vorgesehen sein, dass der Lauf
des zu untersuchenden Programms gestoppt wird oder zumindest die
eingangs genannte Zuordnung erfolgt.
-
Es
wird so nicht nur festgestellt, dass ein Speicherleck vorliegt,
sondern es kann durch das Anhalten im Augenblick der Feststellung
eines Speicherlecks auch der Laufzeitpunkt bzw. der Ort im abgelaufenen
Programm ermittelt werden, an dem das Speicherleck entstanden ist.
Ein Programmierer hat so erfindungsgemäß eine sehr einfache Möglichkeit, neben
der Feststellung eines Speicherlecks dieses auch zu lokalisieren
und den Fehler in der Programmierung zu beheben.
-
Ein
gefundenes Speicherleck kann somit mit dem erfindungsgemäßen Verfahren
zu einem Bereich eines abgelaufenen Programms durch Anhalten oder
sonstige Weise, z.B. tracen/tracken, zugeordnet werden.
-
Neben
der Möglichkeit
das Programm zu stoppen bei der Feststellung eines Speicherlecks
bei gefundenem Muster kann alternativ oder kumulativ eine Zuordnung
des gefundenen Speicherlecks zu einem Programmbereich, wo der Fehler
entstanden ist abgespeichert werden. So kann das Programm in dieser
Ausführung
auch durchlaufen werden, der Programmierer hat jedoch durch eine
solche Zuordnungsliste die Möglichkeit
die Fehler im Programm zu finden.
-
Ein
Ausführungsbeispiel
wird anhand der nachfolgenden Figuren näher beschreiben.
-
Es
zeigen:
-
1:
zeigt eine Darstellung des Verfahrens als Ablaufplan
-
2:
zeigt einen Auszug aus einer Speicherleck-Liste z.B. von Microsoft
-
3:
zeigt Informationen einer Zeile in der Speicherleck-Liste
-
4:
zeigt Gegenüberstellung
zweier zu Normdateien umgewandelter Speicherlecks
-
5:
zeigt die erkannten Speicherleck-Muster nach der Differenzeinheit
-
6: zeigt die Beschreibung der Suche von gespeicherten
Vergleichsmustern
-
Ausgangspunkt
des hier beispielhaft dargestellten erfindungsgemäßen Verfahrens
gemäß 1 sind
zwei Programmdurchläufe 101 der
programmierten Software des Entwicklers, die daraufhin untersucht
wird, ob sie durch Fehlprogrammierung Speicher reserviert, der nach
Benutzung nicht mehr freigegeben wird. Dabei sind die beiden Programmdurchläufe in einem
gemeinsamen Kasten 101 schematisch dargestellt.
-
Bei
jedem der beiden Programmdurchläufe wird
eine Speicherleck-Liste 103a bzw. 103b z.B. durch
die Microsoft Visual Studio Entwicklungsumgebung oder durch ein
anderes Programm, welches parallel zum Programmlauf auf dem Computer
ablaufen kann, erstellt, welche alle während das Programmlaufs erzeugten
Speicherlecks protokolliert, ohne das hieraus der Ort der Entstehung
im Programm ermittelbar ist.
-
In
der 2 ist exemplarisch ein Auszug aus einer solchen
Liste 103a bzw. 103b dargestellt. Eine solche
Speicherleck-Liste kann eine Vielzahl von Informationen umfassen,
z.B. die Informationen 201, die, wie in 3 extrahiert
gezeigt, über
Dateiname 301, Zeilennummer 302, Allokationsnummer 303, Speicheradresse 304 und
Speicherblockgröße 305 Auskunft
geben.
-
An
dieser Stelle soll darauf hingewiesen werden, dass auch andere Ausgangsinformationen
verwendet werden können,
wobei für
das erfindungsgemäße Verfahren
exemplarisch der Ort eines Speicherlecks durch eine relative Angabe
der Position bzw. des Abstandes zu einem vorhergehenden Speicherleck
verwendet wird, der hier aus der Allokationsnummer herausgelesen
werden kann durch Differenzbildung zweier aufeinander folgender
Allokationsnummern. Weiterhin wird erfindungsgemäß die Größe des Speicherlecks verwendet,
die direkt aus der Liste 103a bzw. 103b durch
eine Längenangabe 305 gegeben
ist und z.B. als Klartext ausgelesen werden kann.
-
Aus
einer jeweiligen Speicherleck-Liste 103a/b kann z.B. mittels
eines Programms 104a bzw. 104b, welches auf demselben
Computer ablaufen kann und in einem bevorzugten Beispiel als Ausleseskripts 104,
welches im Anhang beigefügt
ist, der Inhalt jeder Speicherleck-Liste 103a bzw. 103b in
ein z.B. normiertes Format umgewandelt werden bzw. in eine jeweils
neue Datei 105a/105b extrahiert werden, in welcher
die Eigenschaftsinformationen, welche die Position zum vorhergehenden
Speicherleck und die Speichergröße des Speicherlecks
umfassen, gespeichert werden.
-
Der
Inhalt möglicher
Dateien 105a/b ist in 4 dargestellt.
Dabei ist z.B. in jeder Datei die Information als Tupel in geschweiften
Klammern dargestellt. Der erste Eintrag im Tupel bestimmt die Position,
welche dem Abstand zum vorhergehenden Speicherleck entspricht, und
der zweite die Größe des Speicherlecks,
wobei jede Zeile einen neuen Speicherleck Eintrag umfasst. Die beiden
Spalten 401 und 402 sind Auszüge aus den jeweiligen Dateien 105a und 105b,
welche durch die zwei identischen Programmabläufe 101 entstehen.
-
Wie
beschrieben, führen
zwei identische Programmdurchläufe 101 insbesondere
bei großen und
GUI-(Graphical User Interface)intensiven Programmen nicht zu identischen
Speicherleck-Listen. Dies liegt u. a. daran, dass das Betriebssystem
während
des Programmdurchlaufs 101 Systemaufrufe und Interrupts
selbständig
und zu nicht vorhersehbaren Zeiten ausführt. Um diese Einflüsse zu eliminieren
und um die effektiven Speicherlecks zu bestimmen, erfolgen mindestens
zwei identische Programmabläufe 101,
zu denen jeweils die Speicherleckliste 103a/b bestimmt
wird (a indiziert den ersten und b den zweiten Durchlauf).
-
Aus
den Speicherleck-Listen 103a/b wird jeweils die Datei 105a/b über das
Ausleseskript 104a/b ermittelt. In den jeweiligen Normdateien 105a/b
liegen die Informationen über
Speicherlecks vor, die zwar durch ihre Entstehung wiederkehrende
Informations-Muster aufweisen, jedoch nicht immer an denselben Positionen
in der Datei auftreten.
-
Um
für eine
spätere
Lokalisierung während eines
Programmlaufs Vergleichsmuster zu erzeugen, werden die Dateien 105a/b
einer Differenzeinheit 107 zugeführt. Die Differenzeinheit 107 ist
beispielsweise durch eine Software realisiert, die auf demselben Computer
ablaufen kann und z.B. die programmtechnische Umsetzung des „LCS(Longest
Common Subsequence)"-Algorithmus
oder des „Diff"-Algorithmus beinhaltet, welche in der
Lage sind, Muster zu erkennen die z.B. auf der Erkennung der längsten zusammenhängenden
Zeichenfolge basieren.
-
In
der 5 ist ein Beispielauszug für die Ausgabe einer Differenzeinheit 107,
welche den „beyond
compare"-Algorithmus
umgesetzt hat, angegeben. Die Spalten 501 und 502 kennzeichnen
die Zeilennummern der Dateien 105a und 105b bei
denen übereinstimmende
Tupel gefunden wurden. Durch die horizontal angeordneten gestrichelten
Linien 503 werden zusammengehörige Teile abgegrenzt, die
so ein Speicherleck-Muster kennzeichnen, welches als Vergleichsmuster
dienen kann. Weiterhin sind analog zu 4 die relativen
Positionen und die Größen der
Speicherlecks durch die Tupel angezeigt.
-
Betrachtet
man die 4 so ist erkennbar, dass in
den Zeilen 1 des Eintrages in beiden Dateien 105a und b
eine Übereinstimmung
besteht im jeweiligen Tupel 0,48. Diese Information wird als Muster erkannt
und wie in der 5 gezeigt abgespeichert als
1,1,0,48. In der zweiten Zeile gibt es keine Übereinstimmung. Die nächste Übereinstimmung
gibt es bei den Zeilen 3 und 4 durch die Tupel 56,54 und 388,46.
Durch diese vergleichende Suche wird sukzessive die Liste bzw. Datei
gemäß 5 erstellt, wobei
in der 5 nur exemplarisch ein Auszug zu sehen ist.
-
Ein
weiteres erkanntes Muster ist z.B. durch die Bezugsziffer 505 gegeben.
Dieses Muster umfasst drei Einträge
als eine weitere mögliche
zusammenhängende Übereinstimmung
zwischen den Dateien 105a und 105b. Darauf folgt
ein Muster mit vier Einträgen,
dann wieder eines mit nur einem Eintrag.
-
Für eine effektive
Weiterbenutzung, kann das Ergebnis der Differenziereinheit 107,
um Einzeleinträge,
wie z.B. den Eintrag 504, welche einem Speicherleck Muster
mit einer Eintragung entsprechen, und um Einträge mit großem Abstand zum vorhergehenden
Eintrag z.B. wie in der vierten und dreizehnten Zeile in 4 bereinigt
werden, obwohl hier eine Übereinstimmung
besteht, insbesondere wofür eine
separate Einheit 109 zur Verfügung stehen kann.
-
In
einer besonderen Ausführungsform
werden dabei Tupel mit Abständen >100 nicht als Beitrag zu
einem Muster berücksichtigt,
da diese Beiträge wahrscheinlich
nicht aus dem gleichen Grund wie die anderen Speicherlecks zum Muster
beitragen. Dementsprechend sind Einträge mit solchen zu großen Abständen in
der 5 nicht aufgelistet.
-
Die
verbleibenden Speicherleck Muster werden nacheinander als spätere Vergleichsmuster
für einzelne
Programmläufe
z.B. in die Registry Datei 111 eingetragen. Danach erfolgt
ein weiterer Programmdurchlauf 113, wobei die gespeicherten
Vergleichsmuster zur Laufzeit gesucht und ausgewertet werden.
-
Die
Abfolge der im Programmlauf auftretenden Speicheranforderungen wird
mit dem in der Registry abgelegten und beim Programmstart von dort eingelesenen
Muster verglichen und beispielsweise in der Allokationsliste 115 protokolliert.
Die Informationen der Allokationsliste können mit in eine Debug-Ausgabe
aufgenommen werden, welche sämtliche
Informationen umfassen, die während
des Programmlaufs intern generiert werden. Somit enthält die gesamte
Debug-Ausgabe die Information bei welchem Muster auch ein Speicherleck
auftrat.
-
In
einem Beispiel kann bei der achten Mustererkennung tatsächlich ein
protokolliertes Speicherleck vorgelegen haben. Diese Information
kann wiederum in die Registry-Datei 119 geschrieben 117 und
bei erneutem Auftreten – achtes
vorkommen des Musters entspricht einem Speicherleck – wird der
erneute Programmablauf 121 angehalten und in den entsprechenden
Quelltext 123 (Programmierbereichen) gesprungen (entspricht
der Einführung
eines Breakpoints in die Registry).
-
Beschreibung der Mustersuche
-
Bei
der Suche nach den Programmstellen, an denen ein Speicherleck verursacht
wird, ist das Anhalten der Programmausführung in dem Moment, an dem
eine Allokation durchgeführt
wird, die auf das vorgegebene Muster passt (woher dieses auch immer
kommen mag), ein zentraler Bestandteil.
-
Dazu
wird während
eines Programmlaufes eine Service-Routine, insbesondere bei den
elementaren Laufzeit-Bibliotheken der Programmierumgebung (in der
vorliegenden Ausführung
sind das: Microsoft Visual C++ mit ihrer CRT-Bibliothek) angemeldet,
die dann bei jeder Speicherallokation aufgerufen wird und dabei
als Argument mindestens die angeforderte Speicherblockgröße übergeben
bekommt. Diese angeforderten Speicherblockgrößen bzw. -längen werden nacheinander in
eine Allokationsliste eingetragen.
-
Die
zu suchenden Vergleichsmuster können aus
einer Folge von Speicherallokationen, repräsentiert durch Zahlenpaare
bestehen, wobei die erste Zahl den Abstand zur vorherigen Allokation
darstellt und die zweite die angeforderte Speicherblockgröße. Die
Muster können
wie zuvor beschrieben durch wenigstens zwei nacheinander ausgeführte Programmläufe erstellt
werden.
-
Diese
Paare lassen sich jetzt in eine lineare Liste von Einzelwerten,
eine Musterliste umformen, indem die Felder in den richtigen Abständen mit
den Speicherblockgrößen ausgefüllt werden
und die Zwischenfelder eine Null erhalten. Die 6a zeigt
eine solche Musterliste.
-
Während des
Programmlaufes werden die auflaufenden Speicherallokationen in einer
Allokationsliste mitprotokolliert, insbesondere wobei diese aus
logischen Gründen
nicht länger
sein muss als die Musterliste. Dort werden die Allokationen vermerkt, insbesondere
indem die jüngste
Allokation am vorderen Ende eingetragen wird und alle vorherigen
Allokationen eine Position nach rechts rücken. Eine solche Allokationsliste
zeigt die 6b.
-
Nach
jeder erfolgten Allokation und Eintragung in die Allokationsliste
wird diese gegen die Musterliste verglichen. Dabei werden nur Felder
berücksichtigt,
die in der Musterliste ungleich Null sind. Dies zeigt 6c in
der die Übereinstimmungen
dunkel hinterlegt sind.
-
Wenn
sich dabei (wie abgebildet) eine Übereinstimmung der Feldinhalte
von oberer Musterliste und unterer Allokationsliste ergibt, ist
das Muster erfolgreich erkannt worden. In diesem Falle kann der Programmablauf
angehalten werden und der Programmierer erhält hierdurch den Hinweis auf
den Ort der Entstehung des Fehlers.
-
Die
hier beschriebenen Ausführungen
sind nicht beschränkend
zu verstehen und lassen sich insbesondere auch einzeln oder in der
Gesamtheit kombinieren mit den Ausführungen im allgemeinen Teil der
Beschreibung.
-
Anhang: Quelltext des Ausleseskripts
-
- Imports System
Imports EnvDTE
Imports EnvDTE80
Imports
Microsoft.Win32
Imports System.Diagnostics
Imports System.Collections.Generic
Imports
System.Text.RegularExpressions
Imports System.Windows.Forms
Public
Module MemoryLeaks
Function MakeHexStr(ByVal Number, ByRef
Count)
Dim HexString As String
Dim i As Integer = 0
For
i = 0 To 3
Dim ByteVal As Integer = Number Mod 256
Dim
HexDigit As String = Hex(ByteVal)
If Len(HexDigit) = 1 Then
HexDigit
= "0" + HexDigit
End
If
HexString = HexString + HexDigit + ","
Number
= (Number – ByteVal)/256
Next
Count
= Count + 1
If Count Mod 4 = 0 Then
HexString = HexString
+ "\" + vbCrLf + " "
End If
MakeHexStr = HexString
End
Function
Function ExtractLeakPatterns() As String
Dim
Pattern Text As String
Dim MemLeakDump As TextDocument = DTE.ToolWindows.OutputWindow.ActivePane.TextDocument
MemLeakDump.Selection.StartOfDocument()
If
MemLeakDump.Selection.FindText("Speicherlecks") Then
Dim oRe
As Regex
Dim base As Integer = 0
Dim lastLine As Integer
= 0
Do While MemLeakDump.Selection.FindText("bytes long")
'if the current line
is less than the previous, we passed the end of the file!
If
MemLeakDump.Selection.CurrentLine <=
lastLine Then
Exit Do
Else
'remember line number of current occurence
lastLine
= MemLeakDump.Selection.CurrentLine
End If
'select the whole
line
MemLeakDump.Selection.SelectLine()
Dim lineText As
String = MemLeakDump.Selection.Text
oRe = New Regex(".*{([0–9]+)}.*([0–9]+) bytes.*")
If oRe.IsMatch(lineText)
Then
Dim AllocText As String = oRe.Replace(lineText, "$1")
Dim SizeText
As String = oRe.Replace(lineText, "$2")
If
base = 0 Then
base = CLng(AllocText)
End If
Dim AllocNum
As Integer = base – CLng(AllocText)
If
AllocNum < 0 Then
Exit
Do
End If
Pattern Text = PatternText + "{" + Format(AllocNum) + "," + Format(Val(SizeText)) + "}" + vbCrLf
base = CLng(AllocText)
End
If
Loop
End If
ExtractLeakPatterns = Pattern
Text
End Function
Sub BuildMemLeakPattern()
'DESCRIPTION: Creates
a Speicherleck match pattern from a selected portion of debug output
text
'Create
a new text document.
DTE.ItemOperations.NewFile("General\Text File", "MemLeakPattern")
ActiveDocument.Selection.Text
= ExtractLeakPatterns()
End Sub
Sub BuildMemLeakPatternFile()
Dim
PatternText As String = ActiveDocument.Selection.Text
Dim RegFileText
As String
Dim NumCount As Integer = 0
Dim oRe As Regex
oRe
= New Regex("{([0–9]+),([0–9]+)}")
Dim AllMatches
As Match = oRe.Match(PatternText)
Do While AllMatches.Length > 0
Dim CurrMatch
As String = AllMatches.Value
Dim AllocNum As Integer = oRe.Replace(CurrMatch, "$1")
If NumCount
= 0 Then
AllocNum = 0
End If
Dim SizeNum As Integer
= oRe.Replace(CurrMatch, "$2")
Dim j As Integer
For
j = 2 To AllocNum
RegFileText = RegFileText + MakeHexStr(0,
NumCount)
Next
RegFileText = RegFileText + MakeHexStr(SizeNum, NumCount)
AllMatches
= AllMatches.NextMatch
Loop
'Create a new text document.
DTE.ItemOperations.NewFile("General\Text File", "MemLeakPattern.reg")
If NumCount
= 0 Then
ActiveDocument.Selection.Text = "No valid Speicherleck patterns selected"
Elself RegFileText.Length > 3000 Then
ActiveDocument.Selection.Text
= "Speicherleck
patterns too large"
Else
Dim
CountText As String = MakeHexStr(NumCount, NumCount)
'create appropriate
.reg file
ActiveDocument.Selection.Text =_
"REGEDIT4" + vbCrLf + vbCrLf_
+ "[HKEY_CURRENT_USER\Software\dSPACE\CalDesk\MemLeakTracking]" + vbCrLf_
+ """Enable""=dword:00000001" + vbCrLf_
+ """Pattern""=hex:" + CountText + RegFileText + "00" + vbCrLf_
+ """BreakAtMatchNo""=dword:00000000" + vbCrLf_
+ """HideLeaksUntilMatch""=dword:00000000" + vbCrLf_
+ """HideLeaksAfterMatch""=dword:00000000" + vbCrLf
End If
End Sub
Sub
CheckMemLeakHits()
Dim mDict As SortedDictionary(Of Integer,
Integer) = New SortedDictionary(Of Integer, Integer)
Dim oRe
As Regex = New Regex("matches
\( *([0–9]+)\)[a–z]+([0–9]+)")
Dim MemLeakDump
As TextDocument = DTE.ToolWindows.OutputWindow.ActivePane.TextDocument
MemLeakDump.Selection.StartOfDocument()
Do
While MemLeakDump.Selection.FindText("*** Condition matches")
MemLeakDump.Selection.SelectLine()
Dim
TheMatch As Match = oRe.Match(MemLeakDump.Selection.Text)
If
TheMatch.Length > 0
Then
Dim CurrMatch As String = TheMatch.Value
Dim MatchNum
As Integer = oRe.Replace(CurrMatch, "$1")
Dim
AllocNum As Integer = oRe.Replace(CurrMatch, "$2")
mDict.Add(AllocNum,
MatchNum)
End If
Loop
For Each match As KeyValuePair(Of
Integer, Integer) In mDict
MemLeakDump.Selection.StartOfDocument()
If
MemLeakDump.Selection.FindText("{" + Format(match.Key)
+ "}") Then
Dim reg
As RegistryKey = Registry.CurrentUser
reg = reg.OpenSubKey("Software")
reg = reg.OpenSubKey("dSPACE")
reg = reg.OpenSubKey("CalDesk")
reg = reg.OpenSubKey("MemLeakTracking", True)
reg.SetValue("BreakAtMatchNo", match.Value)
MessageBox.Show("Match number" + Format(match.Value)
+ "is indeed a Speicherleck
and has been activated for debug-break", "Success")
Exit For
End
If
Next
End Sub
End Module