Systemnahe Programmierung in C/C++ – Modularisierung, Makefiles und Debugging – Knut Stolze [email protected] Lehrstuhl für Datenbanken und Informationssysteme Fakultät für Mathematik und Informatik 2006–11–08 Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 1 / 42 Agenda 1 Modularisierung Module Bibliotheken 2 Makefiles 3 Debugging & Tracing Debugging Tracing Profiling Speicherverwaltung 4 Aufgaben Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 2 / 42 Outline 1 Modularisierung Module Bibliotheken 2 Makefiles 3 Debugging & Tracing Debugging Tracing Profiling Speicherverwaltung 4 Aufgaben Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 3 / 42 Modularisierung 1 Dateiintern: Aufteilung von Funktionen in verschiedene Übersetzungseinheiten ⇒ Nicht weiter diskutiert 2 3 Objektebene: Module als Mechanismus ähnlich zum Klassenkonzept in OO-Programmiersprachen Packaging: Implementierung von Bibliotheken ⇒ Bereits bekannt 4 Architekturebene: Prozesse vs. Threads ⇒ Nächste Woche Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 4 / 42 Module Einzige höhere Abstraktion in C (Klassen in Java/C++) ⇒ Reichlich Gebrauch davon machen Modul definiert Struktur Alle Funktionen erhalten Zeiger auf Stuktur als ersten Parameter Header: #if !defined(__MODULE_H__) #define __MODULE_H__ struct mod_data; mod_data* mod_open(char *init, ...); int mod_action(mod_data *dat, int arg1, char *arg2, ...); int mod_close(mod_data *dat); #endif Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 5 / 42 Module (cont.) #include "module.h" struct mod_data { long internal_state; ... } /* private */ int function(int arg, ...) { ... } /* public */ mod_data* mod_open(char *init, ...) { ... } Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 6 / 42 Module – Tipps Schnittstelle sauber entwerfen Schnittstelle im Header-File dokumentieren Schnittstelle auch auf Testbarkeit hin gestalten Header gegen Mehrfachinklusion schützen APIs symmetrisch gestalten (open – close) Defensiv programmieren Funktion bei Fehlern so schnell wie möglich beenden Bei Fehler definierten Zustand hinterlassen Argumente von extern aufgerufenen Funktionen immer validieren Globale Variablen mit static schützen Kein Zugriff auf Variablen anderer Module (mittels external) Accessor-Funktionen einsetzen Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 7 / 42 Bibliotheken 1 Zur Compile-Zeit hinzuge„link“t ⇒ Bereits bekannt 2 Dynamisch zur Laufzeit geladen Funktionen: dlopen, dlclose und dlsym Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 8 / 42 Dynamische Verwendung von Bibliotheken void *dlopen(const char *filename, int flag) Lädt angegebene Bibliothek Gibt DLL-Handle zurück Verschiedene Optionen zur Kontrolle des Ladevorgangs int dlclose(void *handle) Schliesst geladene Bibliothek Gibt Resourcen frei void *dlsym(void *handle, const char *symbol) Gibt Addresse des angegebenen Symbols ⇒ Zeiger auf Variable oder Funktionszeiger Funktionsnamen in C eindeutig ⇒ Symbol = Funktionsname C++ hat Name Mangeling Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 9 / 42 Dynamische Verwendung von Bibliotheken void *dlopen(const char *filename, int flag) Lädt angegebene Bibliothek Gibt DLL-Handle zurück Verschiedene Optionen zur Kontrolle des Ladevorgangs int dlclose(void *handle) Schliesst geladene Bibliothek Gibt Resourcen frei void *dlsym(void *handle, const char *symbol) Gibt Addresse des angegebenen Symbols ⇒ Zeiger auf Variable oder Funktionszeiger Funktionsnamen in C eindeutig ⇒ Symbol = Funktionsname C++ hat Name Mangeling Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 9 / 42 Dynamische Verwendung von Bibliotheken void *dlopen(const char *filename, int flag) Lädt angegebene Bibliothek Gibt DLL-Handle zurück Verschiedene Optionen zur Kontrolle des Ladevorgangs int dlclose(void *handle) Schliesst geladene Bibliothek Gibt Resourcen frei void *dlsym(void *handle, const char *symbol) Gibt Addresse des angegebenen Symbols ⇒ Zeiger auf Variable oder Funktionszeiger Funktionsnamen in C eindeutig ⇒ Symbol = Funktionsname C++ hat Name Mangeling Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 9 / 42 Outline 1 Modularisierung Module Bibliotheken 2 Makefiles 3 Debugging & Tracing Debugging Tracing Profiling Speicherverwaltung 4 Aufgaben Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 10 / 42 Makefiles Besteht aus Menge von Regeln Steuert Übersetzung von Programmen Ziel: Quelle Quelle ... Shellkommando Shellkommando ... Ziel ist Name einer Datei Gibt an, welche Datei erzeugt wird Falls eine Quelle neuer als Ziel, werden Kommandos ausgeführt Quelle kann in anderen Regeln andere Vorraussetzungen haben Aktualität und Existenz der Quellen wird rekursiv behandelt Shellkommandos müssen Ziel aus Quellen erzeugen Müssen durch <TAB> eingeleitet werden Voranstellung: ’-’ ignoriere Fehler ’@’ Kommando selbst nicht ausgeben Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 11 / 42 Makefile – Beispiel prog: mod1.o mod2.o mod3.o gcc mod1.o mod2.o mod3.o -lm \ -lglib -o prog mod1.o: mod1.c gcc -Wall -O2 -c mod1.c mod2.o: mod2.c gcc -Wall -O2 -c mod2.c mod3.o: mod3.c gcc -Wall -O2 -c mod3.c Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 12 / 42 Variablen & Funktionen Wiederholter Text kann durch Variablen ersetzt werden Variablen als Listen interpretiert Funktionen zur Manipulation SOURCES := mod1.c mod2.c mod3.c OBJECTS := $(patsubst .c, .o, $(SOURCES)) CC := gcc prog: $(OBJECTS) $(CC) $(OBJECTS) -lglib -o prog Spezielle Variablen: $@ Ziel $< Erste Quelle $∧ Alle Quellen (über mehrere Regeln) $? Quellen, die aktueller als Ziel sind Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 13 / 42 Spezielle Regeln Regeln mit Mustern Platzhalter % definiert Regelmengen Kommandosequenzen können zusammengefasst und 1x definiert werden Verwendung wie Variablen Mit define ... endef definiert Regeln für häufig vorkommende Anwendungsfalle bereits in make eingebaut Siehe info make Möglichst wenig verwenden weil implizit Phony Targets Ziele, für die nie eine gleichnamige Datei erzeugt wird clean: rm -f *~ *.o core prog .PHONY: clean Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 14 / 42 Beispiel SOURCES := mod1.c mod2.c mod3.c OBJECTS := $(patsubst .c, .o, $(SOURCES)) CC := gcc CFLAGS := -Wall -O2 define link-source $(CC) $(OBJECTS) -lglib -o prog endef define compile-source $(CC) $(CFLAGS) -c $< -o $@ endef prog: $(OBJECTS) $(link-source) %.o: %.c $(compile-source) Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 15 / 42 Abhängigkeiten Abhängigkeiten können automatisch generiert werden Von C/C++ Quellcode Kommando makedepend Teil von X11 Kompileroption -M für gcc Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 16 / 42 Strukturierung von Makefiles Abhängigkeiten oft in separate Dateien ausgelagert Z. B. .dep oder .make.dep Plattformabhängige Einstellungen separiert Z. B. unterschiedliche Compiler auf verschiedenen Plattformen Komponentenspezifische Makefiles include ../makefile.aix Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 17 / 42 Outline 1 Modularisierung Module Bibliotheken 2 Makefiles 3 Debugging & Tracing Debugging Tracing Profiling Speicherverwaltung 4 Aufgaben Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 18 / 42 Debugging Schrittweises Nachvollziehen der Logik eines Programms und seiner Funktionen Direkter Zugriff auf und Modifikation von Variablen und Speicherinhalt Programm muss vor dem Debugging nicht übersetzt oder geändert werden Debug-Informationen jedoch notwendig Compiler-Option -g Übersetzung mit Optimierung beeinflusst Abbildung zwischen Quelltext und Maschinencode Nicht Option -Ox verwenden Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 19 / 42 Debugging Schrittweises Nachvollziehen der Logik eines Programms und seiner Funktionen Direkter Zugriff auf und Modifikation von Variablen und Speicherinhalt Programm muss vor dem Debugging nicht übersetzt oder geändert werden Debug-Informationen jedoch notwendig Compiler-Option -g Übersetzung mit Optimierung beeinflusst Abbildung zwischen Quelltext und Maschinencode Nicht Option -Ox verwenden Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 19 / 42 Debugging Schrittweises Nachvollziehen der Logik eines Programms und seiner Funktionen Direkter Zugriff auf und Modifikation von Variablen und Speicherinhalt Programm muss vor dem Debugging nicht übersetzt oder geändert werden Debug-Informationen jedoch notwendig Compiler-Option -g Übersetzung mit Optimierung beeinflusst Abbildung zwischen Quelltext und Maschinencode Nicht Option -Ox verwenden Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 19 / 42 Debugger 1 Bearbeiten von bereits laufenden Programmen möglich ⇒ Debugger verbindet sich zu existierenden Prozess Option „attach“ (häufig -a) 2 Analysieren von core Dateien Eine Art Log bei Programmabstürzes Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 20 / 42 Core Dumps Datei, die bei bestimmten Signalen geschrieben wird SIGQUIT, SIGILL, SIGABRT, SIGFPE, SIGSEGV, SIGBUS, SIGSYS, SIGTRAP, SIGXCPU, SIGXFSZ Image des Speichers eines Prozesses Heap + Stack Implizit Aufrufreihenfolge von Funktionen bekannt Größe von core Dateien kann limitiert werden Funktion getrlimit Kommando ulimit Core wird nicht geschrieben, wenn Keine Rechte im Zielverzeichnis core existiert bereits und ist read-only Größe auf 0 Bytes beschränkt ... Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 21 / 42 Typische Debuggerfunktionalität Run ⇒ Starte Programm evtl. mit zusätzlichen Kommandozeilenoptionen Breakpoint setzen ⇒ Programmausführung wird beim Erreichen unterbrochen Debugger sendet Signal an Prozess Next ⇒ Führe einen Schritt in Funktion aus Step ⇒ Steige in aufgerufene Funktion hinab Wenn nicht möglich, führe einen Schritt in aktuelle Funktion aus Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 22 / 42 Typische Debuggerfunktionalität (cont.) Continue ⇒ Setzt Programmausführung bis zum nächsten Breakpoint fort Keine Schrittweise Abarbeitung Restart ⇒ Starte Programm komplett neu Nötig, wenn Kontrollfluss bereits nach gewünschtem Ereignis ist Backtrace ⇒ Gibt aktuellen Aufruf-Stack aus Print ⇒ Variablen/Datenstrukturen anzeigen (global und lokal) Set ⇒ Setze Wert einer Variable oder Speicherbereichs ... Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 23 / 42 Debugger – Beispiele Kommandozeilen-Debugger gdb $ gdb <programm-name> Unerlässlich: help-Befehl Sehr hilfreich wenn keine graphische Oberfläche verfügbar Grafische Debugger Meist besser und übersichtlicher Quelltext, Variablen, Aufruf-Stack, . . . werden parallel angezeigt ddd GNU Debugger, basiert auf gdb xldb IBM AIX Debugger (bereits in die Jahre gekommen) idebug AIX Debugger Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 24 / 42 Debugger – Beispiele Kommandozeilen-Debugger gdb $ gdb <programm-name> Unerlässlich: help-Befehl Sehr hilfreich wenn keine graphische Oberfläche verfügbar Grafische Debugger Meist besser und übersichtlicher Quelltext, Variablen, Aufruf-Stack, . . . werden parallel angezeigt ddd GNU Debugger, basiert auf gdb xldb IBM AIX Debugger (bereits in die Jahre gekommen) idebug AIX Debugger Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 24 / 42 ddd Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 25 / 42 Internas 1 Debugger startet Programm Debugger & Programm sind ein Prozess ⇒ Debugger kann auf Speicher und Strukturen des Programms zugreifen 2 Debugger verbindet sich zu bereits laufendem Prozess Debugger & Programm sind verschiedene Prozesse Betriebssystem trennt klar beide Adressräume ⇒ Spezielle Systemfunktion erlaubt Zugriff auf Speicher anderer Prozesse Funktion nicht selber nutzen, da sehr schwierig zu handhaben und risikobehaftet Besondere Rechte notwendig Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 26 / 42 Internas 1 Debugger startet Programm Debugger & Programm sind ein Prozess ⇒ Debugger kann auf Speicher und Strukturen des Programms zugreifen 2 Debugger verbindet sich zu bereits laufendem Prozess Debugger & Programm sind verschiedene Prozesse Betriebssystem trennt klar beide Adressräume ⇒ Spezielle Systemfunktion erlaubt Zugriff auf Speicher anderer Prozesse Funktion nicht selber nutzen, da sehr schwierig zu handhaben und risikobehaftet Besondere Rechte notwendig Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 26 / 42 Tracing Programme werden nicht mit Debug-Informationen ausgeliefert. Optimierung Bessere Laufzeit Besseres Cache-Verhalten Starten/Attachen eines Debuggers nicht möglich ⇒ Nachvollziehen des Programmablaufs mit anderen Mitteln Instrumentieren des Codes Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 27 / 42 Tracing Programme werden nicht mit Debug-Informationen ausgeliefert. Optimierung Bessere Laufzeit Besseres Cache-Verhalten Starten/Attachen eines Debuggers nicht möglich ⇒ Nachvollziehen des Programmablaufs mit anderen Mitteln Instrumentieren des Codes Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 27 / 42 Tracing (cont.) Dedizierte Kompontente Sammelt Trace-Informationen bei Bedarf Im fertigen Produkt mit vorhanden Informationen Eintritt & Verlassen von Funktionen Daten an ausgewählten Zwischenpunkten Informationen beschränkt! Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 28 / 42 Tracing (cont.) Dedizierte Kompontente Sammelt Trace-Informationen bei Bedarf Im fertigen Produkt mit vorhanden Informationen Eintritt & Verlassen von Funktionen Daten an ausgewählten Zwischenpunkten Informationen beschränkt! Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 28 / 42 Tracing (cont.) Dedizierte Kompontente Sammelt Trace-Informationen bei Bedarf Im fertigen Produkt mit vorhanden Informationen Eintritt & Verlassen von Funktionen Daten an ausgewählten Zwischenpunkten Informationen beschränkt! Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 28 / 42 Beispiel „System J“ Macros: DBJ_TRACE_ENTRY() DBJ_TRACE_EXIT() DBJ_TRACE_ACTIVE() DBJ_TRACE_DATA1(tracePoint, length1, data1) DBJ_TRACE_DATA2(tracePoint, length1, data1, length2, data2) DBJ_TRACE_DATA3(tracePoint, length1, data1, length2, data2, length3, data3) DBJ_TRACE_NUMBER(tracePoint, str, val) DBJ_TRACE_STRING(tracePoint, str) Einfache Prüfung zum An-/Abschalten des Tracings if (dbj_trace_on) { ...} Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 29 / 42 Profiling Profiling: Wo verbraucht ein Programm seine Zeit? 1 Kompilieren und Linken mit eingeschalteten Profiling GCC-Option -pg 2 Ausführen des Programms, um Profiling-Daten zu sammeln Produziert Datei gmon.out beim Programmende 3 Analysieren der Daten 4 Andere Programme und Mechanismen Programm gprof Valgrind + Visualisierung http://valgrind.org http://kcachegrind.sourceforge.net/ ... Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 30 / 42 gprof – Beispiel gcc profiling.c -pg ./a.out gprof -b -Q a.out % cumulative time seconds 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 Knut Stolze (DBIS) self seconds 0.00 0.00 0.00 0.00 calls 1 1 1 1 self Ts/call 0.00 0.00 0.00 0.00 total Ts/call 0.00 0.00 0.00 0.00 C/C++ Programmierung name fct1 fct1_1 fct1_2 fct2 2006–11–08 31 / 42 Code Coverage Testing Überprüfen, welche Anweisungen und Pfade ausgeführt werden White-Box Testing Tools gcov xSuds Purify JCover ... Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 32 / 42 gcov Arbeiten mit gcc zusammen 1 gcc -fprofile-arcs -ftest-coverage profiling.c 2 ./a.out ⇒ Instrumentiert und übersetzt Programm ⇒ Sammelt Profiling-Informationen 3 gcov -a profiling.c ⇒ Formatiert Profiling-Informationen 4 cat profiling.c.gcov -: 1: 1: 1: 1: ... -: 1: 1: 1: 1: 1: -: Knut Stolze (DBIS) 3:void fct1_1() 4:{ 5: printf("Function 1-1\n"); 5-block 0 6:} 25:int main() 26:{ 27: fct1(); 27-block 0 28: fct2(); 29: return 0; 30:} C/C++ Programmierung 2006–11–08 33 / 42 Speicherverwaltung Nachvollziehen, welche Speicherblöcke allokiert wurden? Wo angefordert? Welche Größe? ⇒ Keine Unterstützung vom Betriebssystem ⇒ Muss Anwendung selbst abdecken Entsprechende Bibliotheken einsetzen Eigene Funktionen schreiben Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 34 / 42 Speicherverwaltung Nachvollziehen, welche Speicherblöcke allokiert wurden? Wo angefordert? Welche Größe? ⇒ Keine Unterstützung vom Betriebssystem ⇒ Muss Anwendung selbst abdecken Entsprechende Bibliotheken einsetzen Eigene Funktionen schreiben Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 34 / 42 Speicherverwaltung Nachvollziehen, welche Speicherblöcke allokiert wurden? Wo angefordert? Welche Größe? ⇒ Keine Unterstützung vom Betriebssystem ⇒ Muss Anwendung selbst abdecken Entsprechende Bibliotheken einsetzen Eigene Funktionen schreiben Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 34 / 42 Systemfunktionen abfangen Bibliothek X mit Funktionen malloc, free etc. Umgebungsvariable LD_PRELOAD lädt X Symbole im Programm werden gegen X aufgelöst ⇒ malloc, free etc. Alle weiteren Symbole gegen libc aufgelöst Accounting in eigener Implementierung Funktionen weitergereicht Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 35 / 42 Systemfunktionen abfangen Bibliothek X mit Funktionen malloc, free etc. Umgebungsvariable LD_PRELOAD lädt X Symbole im Programm werden gegen X aufgelöst ⇒ malloc, free etc. Alle weiteren Symbole gegen libc aufgelöst Accounting in eigener Implementierung Funktionen weitergereicht Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 35 / 42 Systemfunktionen abfangen Bibliothek X mit Funktionen malloc, free etc. Umgebungsvariable LD_PRELOAD lädt X Symbole im Programm werden gegen X aufgelöst ⇒ malloc, free etc. Alle weiteren Symbole gegen libc aufgelöst Accounting in eigener Implementierung Funktionen weitergereicht Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 35 / 42 Systemfunktionen abfangen Bibliothek X mit Funktionen malloc, free etc. Umgebungsvariable LD_PRELOAD lädt X Symbole im Programm werden gegen X aufgelöst ⇒ malloc, free etc. Alle weiteren Symbole gegen libc aufgelöst Accounting in eigener Implementierung Funktionen weitergereicht Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 35 / 42 Outline 1 Modularisierung Module Bibliotheken 2 Makefiles 3 Debugging & Tracing Debugging Tracing Profiling Speicherverwaltung 4 Aufgaben Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 36 / 42 Allgemeine Hinweise Achten Sie auf ordnungsgemäße Fehlerbehandlung in allen Fällen. Alle Resourcen, die eine Programm oder eine Bibliothek verwendet, sind explizit freizugeben. Es soll/darf sich nicht auf das Betriebssystem verlassen werden. (In Bibliotheken kann man das sowieso nicht, und in allen anderen Fällen ist es einfach guter Stil.) Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 37 / 42 Aufgabe 1 – Makefiles Schreiben Sie ein Makefile, welches auf alle nachfolgenden Aufgaben 2-5 zugeschnitten ist und die jeweiligen Dateien übersetzt, „link“t, und ausführt. Zusätzlich ist eine Möglichkeit zum Aufräumen bzw. Löschen aller Dateien, die keine Quelldateien sind, bereitzustellen. Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 38 / 42 Aufgabe 2 – Modularisierung Implementieren Sie ein Modul (siehe Slide 5), welches Strings in einer Struktur verwaltet. Die Struktur hat den String bzw. eine Kopie davon selbständig zu verwalten, d. h. einschliesslich der nötigen Speicherallokationen. Zusätzlich sind folgende Funktionen bereitzustellen: a) Kreieren eines neuen, leeren Strings (Allokieren und Intialisieren), b) Zerstören und Freigeben des Strings und der Struktur, c) Anhängen eines C-Strings (Typ char *), d) Konkatenieren von zwei Strings, die in besagten Strukturen verwaltet werden, e) Ermitteln der aktuellen Länge des Strings, f) Ermitteln der Länge des aktuell allokierten Puffers. Wir nehmen an, dass keine Multibyte-Zeichensätze verwendet werden und damit keine Konvertierungen zwischen Zeichensätzen nötig sind. Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 39 / 42 Aufgabe 3 – Profiling/Coverage Schreiben Sie ein Programm, dass die verschiedenen Funktionen des Moduls aus Aufgabe 2 verwendet und testet. Die Funktionen aus Aufgabe 2 können entweder direkt (also .o-Datei) hinzuge„linkt“ oder als Bibliothek (shared library) eingebunden werden. a) Nutzen Sie Profiling, um zu überprüfen, welche Funktionen die meiste Zeit benötigen. (Eventuell benötigen Sie eine Reihe von Aufrufen, um aussagefähige Zahlen zu erhalten.) b) Verwenden Sie gcov um die Code Coverage des Moduls durch Ihr Testprogramm zu ermitteln. Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 40 / 42 Aufgabe 4 – Speicherauditing Implementieren Sie eigene Versionen aller dynamischen C Speicherfunktionen, die nachvollziehen, wann ein Speicherblock allokiert (in welcher Größe), und wann er wieder freigegeben wurde. Bauen Sie eine Bibliothek (shared library) in der die Funktionen aufgenommen werden. Verwenden Sie diese Bibliothek, um die Nutzung des Speichers (Heaps) durch das Testprogramm von Aufgabe 3 nachzuvollziehen. Dafür ist gegebenenfalls der Quelltext von Aufgabe 2 und 3 anzupassen, damit die neuen Funktionen verwendet werden. Das Nachverfolgen der Speicheroperationen soll mit einer Umgebungsvariable an- bzw. abgeschaltet werden können. Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 41 / 42 Aufgabe 5 – Dynamische Bibliotheken Implementieren Sie ein Programm, welches die Bibliothek aus Aufgabe 4 dynamisch lädt, und die 5 Speicherfunktionen (welche sind das?) aus der Bibliothek ermittelt und Funktionszeigern zuweist. In 2-3 Beispielen sind diese Funktionszeiger bei Speicheroperationen zu verwenden. Zwischendurch ist die Bibliothek wieder zu entladen, und die regulären Speicherfunktionen (malloc, realloc etc.) sind zu verwenden – selbstverständlich über die Funktionszeiger. Knut Stolze (DBIS) C/C++ Programmierung 2006–11–08 42 / 42