Ausprägungen der dynamischen Codeanalyse
Transcription
Ausprägungen der dynamischen Codeanalyse
MÖGLICHKEITEN UND GRENZEN IN DER DYNAMISCHEN CODEANALYSE VON C++ SOFTWARE Von Matthias Neumann 19.01.2015 Inhaltsangabe • Einleitung • Ausprägungen der dynamischen Codeanalyse • Debugging • Logging • Testing • Profiling • Profiling im Detail • Technische Realisierungsmöglichkeiten • Messkriterien für Profiling • Auswirkungen auf das zu analysierende Programm 2/35 19.01.2015 Inhaltsangabe 3/35 • Abgrenzung zur statischen Codeanalyse • Definitionder statischen Codeanalyse • Durch Menschen • Durch automatisierte Werkzeuge • Vergleich von dynamischer und statischer Codeanalyse • Vor- und Nachteile der statischen Codeanalyse • Vor- und Nachteile der dynamischen Codeanalyse • Fazit 19.01.2015 EINLEITUNG 4/35 19.01.2015 5/35 Einleitung • Komplexität von Software wächst stetig • Trotz Komplexität muss Qualität gewährleistet werden • Mängel müssen so früh wie möglich lokalisiert werden • Dynamische und statische Codeanalyse unterstützen bei der Fehlersuche • Dynamische Codeanalyse untersucht Laufzeit-Fehler 19.01.2015 6/35 • Dynamische Codeanalyse brisantes Thema • Jährliche Konferenz (“Workshop on Dynamic Analysis”) • Relevant bei INFORM für ein Projekt am Frankfurter Flughafen • Dabei müssen Zeitvorgaben bei der Verarbeitung von xml- Telegrammen eingehalten werden • In der Ausarbeitung wurden deshalb die Möglichkeiten der dynamischen Codeanalyse evaluiert 19.01.2015 AUSPRÄGUNGEN der dynamischen Codeanalyse 7/35 19.01.2015 Ausprägungen 8/35 Allgemeines • Jegliche Analyse des Programms, die während der Laufzeit stattfindet • Durch die Ergebnisse dieser Analyse können Schwachstellen im Code lokalisiert werden 19.01.2015 Ausprägungen 9/35 Debugging • Ist ein Hilfsprogramm, das die Variablenwerte darstellt und schrittweise den Programmcode durchläuft • Aufruflisten geben Informationen über Aufrufhierarchien der Funktionen • Option beim Kompilieren unter GCC • Debug-Modus unter Visual Studio • Zusätzliche Informationen werden im Executable hinterlegt (Dateigröße nimmt zu) 19.01.2015 Ausprägungen Logging • Logger protokolliert die Aktionen eines Programms • Auch nach Absturz Laufzeitinformationen • Ausgabe der Logs benötigt Ressourcen (IO) 10/35 19.01.2015 Ausprägungen 11/35 Testing • Ausführung des Programms mit dem Ziel Fehler zu finden • Black-Box-Testing • Tester kennt innere Strukturen nicht • Durch Eingaben werden die Ausgaben geprüft • Glass-Box-Testing • Tester kennt interne Logik • Tester schreibt Tests, die bestimmte Passagen des Quellcodes durchlaufen 19.01.2015 Ausprägungen 12/35 Profiling • Externes Werkzeug • Misst bestimmte Laufzeitdaten eines Programmes, wie z.B. • die Anzahl der Aufrufe einer Funktion • Laufzeiten von Funktionen • Speicherauslastungen • Speicherlecks • Codeüberdeckungen 19.01.2015 PROFILING im Detail 13/35 19.01.2015 Profiling 14/35 Technische Realisierungsmöglichkeiten • Manuelle Instrumentierung • Zusätzliche Instruktionen werden dem Programm hinzugefügt • Findet zeitlich vor dem Kompilieren statt • Programmintern werden Werte ermittelt, die nach außen getragen werden Muss eigenständig implementiert + Stark individualisierbar 19.01.2015 ProfilingTechnische Realisierung 15/35 • Instrumentierung zur Compilezeit • Wie manuelle Instrumentierung, aber mit generiertem Code • Compiler fügt zusätzliche Instruktionen vor dem Kompilieren ein • Typischerweise werden Funktionsaufrufe und Hierarchien gemessen und aufbereitet • Bspw: Visual Studio Eingeschränkte Individualisierbarkeit + Kein Programmieraufwand 19.01.2015 ProfilingTechnische Realisierung 16/35 • Binäre Instrumentierung • Findet nach dem Kompilieren statt • Auf binärer Ebene wird das Programm manipuliert, so dass es Messpunkte zur Laufzeit zur Verfügung stellt • Bspw: ATOM Keine Anpassungsmöglichkeiten + Keine Optionen beim Kompilieren + Kein manueller Aufwand 19.01.2015 ProfilingTechnische Realisierung 17/35 • Laufzeitinstrumentierung • Programm läuft in einer virtuellen Maschine, die es observiert (Funktionsaufrufe, Speicherbedarf, etc.) • Bspw: Valgrind Erhebliche Einbußen in der Performanz Durch Virtualisierung sind Umstände anders + Sehr geringer Aufwand + Programm muss nicht manipuliert werden 19.01.2015 ProfilingTechnische Realisierung 18/35 • Sampling • Laufendes Programm wird stichprobenartig geprüft • „Stichproben“ werden in einer bestimmten Frequenz genommen • „Stichproben“ enthalten Informationen über die Funktion, die aktuell ausgeführt wird und dessen Aufrufhierarchie • Relativer Anteil der Stichproben pro Funktion wird berechnet + Nahezu kein Geschwindigkeitsverlust + Keine Manipulation des Programms bzw. dessen Codes Ungenau, da nicht die Aktionen des Programms vernommen werden 19.01.2015 Profiling 19/35 Auswirkungen auf das Programm • Instrumentierung • Zusätzliche Instruktionen verlangsamen das Programm • Größe des Programms nimmt zu (Dateigröße) • Speicherverhalten während der Laufzeit verändert sich 19.01.2015 ABGRENZUNG zur statischen Codeanalyse 20/35 19.01.2015 Abgrenzung 21/35 Statische Codeanalyse • Quellcode wird ohne Ausführung des Programms analysiert • Code wird in textueller Form interpretiert und bewertet • Frühe Fehlererkennung (vor oder während des Kompilierens) • Kann durch automatisierte Werkzeuge oder durch Menschen stattfinden 19.01.2015 AbgrenzungStatische Codeanalyse 22/35 • Durch Entwickler • Selten Überprüfungen auf Syntax, da sehr langwierig (Aufgabe für automatisierte Werkzeuge) • Analyse auf Namenskonventionen und Funktionalität • Dazu gehören: Codeinspektionen, Walkthroughs, Schreibtischtests, Pair-Programming 19.01.2015 23/35 • Durch Werkzeuge • Ermitteln Metriken, Vererbungen, syntaktische Fehler, Abhängigkeiten, etc. indem sie den Quellcode scannen • Ähnliche Aufgaben wie Compiler • Liefern eine aufbereitete Zusammenfassung der Ergebnisse bzw. Warnungen • Visualisierungen, wie Klassendiagramme oder Nassi- Shneidermann-Diagramme • Oft in Entwicklungsumgebungen integriert 19.01.2015 VERGLEICH von dynamischer und statischer Codeanalyse 24/35 19.01.2015 VergleichStatische Codeanalyse 25/35 Vorteile der statischen Analyse + Fehler/Warnungen beziehen sich auf eine exakte Stelle im Code + Gute Integration in Entwicklungsumgebungen • Schnelle Navigation (u.a. durch Outlining) • Statische Typsicherheit • Codegenerierung (Getter, Setter, Deklaration in Header, etc.) • Automatische Vervollständigung sowie passende Vorschläge + Gute Externe Tools wie Lint finden viele potentielle Schwachstellen, die der Compiler übersieht 19.01.2015 VergleichStatische Codeanalyse 26/35 Vorteile der statischen Analyse + Meist nur einmaliger Aufwand nötig + Deckt auch Teile des Codes ab, für die keine Tests formuliert sind 19.01.2015 VergleichStatische Codeanalyse 27/35 Nachteile der statischen Analyse Quellcode muss verfügbar sein Manuelle Analyse fordert hohe Konzentration und Ausdauer Trotzdem möglich, dass Fehler nicht gefunden werden Korrekter Code kann als fehlerhaft deklariert werden Analyse ist nur so gut, wie die definierten Prüfregeln Fehler, die auf bestimmter Hardware auftreten, werden nicht gefunden 19.01.2015 VergleichDynamische Codeanalyse 28/35 Vorteile der dynamischen Analyse + Quellcode nicht zwangsläufig nötig + Fehler im Zusammenhang mit der Hardwarekonfiguration oder Laufzeitumgebung, werden nur in der Ausführung gefunden + Funktionalitäten werden geprüft (gute Testfälle geben Sicherheit, u.a. bei Refactoring) + Laufzeitinformationen (wie Zeitmessungen) nur dynamisch zu ermitteln 19.01.2015 VergleichDynamische Codeanalyse 29/35 Vorteile der dynamischen Analyse + Performance-Tests + Sicherheitslücken, wie unzulässige Speicherzugriffe, Buffer- Overflows, etc. können entdeckt werden + Logging-Mechanismus möglich um auch produktive Systeme zu observieren und Abstürze nachzuvollziehen 19.01.2015 VergleichDynamische Codeanalyse 30/35 Nachteile der dynamischen Analyse Komplexer und daher schwerer in bestehendes Projekt zu integrieren Teilweise muss Code geschrieben werden (manuelle Instrumentierung, Logging, Tests) Schlecht gewählte Testfälle garantieren keine Korrektheit Fehlgeschlagener Test zeigt nur Auslöser nicht Ursache Manipulation des Programmes bei vielen Profilingverfahren nötig 19.01.2015 VergleichDynamische Codeanalyse 31/35 Nachteile der dynamischen Analyse Durch Manipulation wird Verhalten des Programms geändert Dadurch ist es möglich, dass Zeitmessungen unbrauchbar werden Sampling bei wenigen „Stichproben“ nicht repräsentativ 19.01.2015 FAZIT 32/35 19.01.2015 Fazit 33/35 • Weder die statische noch die dynamische Codeanalyse sind objektiv betrachtet besser als die andere • Eher: Ergänzen sich gegenseitig • Schließen sich nicht gegenseitig aus • Finden meistens auch zeitlich in unterschiedlichen Entwicklungsphasen statt • Sinnvoll einzelne Werkzeuge und Verfahren der jeweiligen Analysen zu kombinieren 19.01.2015 Fazit 34/35 • Während der Entwicklung Pair-Programming und Reviews • Lint/cppcheck o.ä. um Konventionen und Schwachstellen zu finden • Testframework (Testfälle dokumentieren Funktionalität) • Zeitkritische Passagen mit Profilern optimieren • Überprüfung auf Speicherlecks mit profiling Tool • Logging Mechanismus (wichtig nach Abstürzen) 35/35 19.01.2015 Noch Fragen? Vielen Dank für Ihre Aufmerksamkeit!