Seminar Effiziente Programmierung Debugging und Speicherfehler
|
|
|
- David Koenig
- vor 7 Jahren
- Abrufe
Transkript
1 Seminar Effiziente Programmierung Debugging und Speicherfehler Arbeitsbereich Wissenschaftliches Rechnen Fachbereich Informatik Fakultät für Mathematik, Informatik und Naturwissenschaften Universität Hamburg Name: Kadir Duman -Adresse: Matrikelnummer: Studiengang: Software System Entwicklung Betreuer: Michael Kuhn Hamburg, den
2 Inhalt 1 Einleitung Debugging Was ist ein Bug? Was ist Debugging? Speicherfehler in C Nicht initialisierte Variablen Der Gültigkeitsbereich Null-Pointer Allocation Memory Allocation Cleared Memory Allocation Speicherlecks Zugriff nach Freigabe Doppelte Freigabe Sanitizer AddressSanitizer MemorySanitizer LeakSanitizer Effizientes Fehlerfinden Suchraum einschränken Delta Debugging Beispiel Zeitnahes Fehlerfinden (Continuous Testing) Valgrind Zusammenfassung Literatur
3 1 Einleitung In diesem Seminar geht es um effiziente Programmierung. Es ist so, dass in Programmen, in der Regel, immer Fehler auftauchen. Es kann dadurch passieren, wenn zum Beispiel neue Funktionen implementiert und hinzugefügt werden, das Quellcode durch einen kompakteren Quellcode ersetzt wird, oder eine Library verändert wird. Dafür ist es wichtig, dass Programmierer Methoden kennen, wie Fehler im Programm erkannt und behoben werden können. Zudem wäre es vorteilhaft, wenn das Erkennen und Beheben von Fehlern schnell passieren kann. Im Folgenden wird zuerst das Thema Debugging beleuchtet, damit der Leser das Grundlegende, wie Fehler gefunden werden können, versteht. Anschließend folgt das Thema Speicherfehler in C. In diesem Thema geht es um die typischen Speicherfehler, die beim Programmieren in der Sprache C entstehen können. Durch diesen Abschnitt soll dem Leser deutlich gemacht werden, worauf geachtet werden muss, damit solche Fehler nicht passieren. Trotzdem kann es vorkommen, dass Speicherfehler auftreten. Um diese Fehler zu finden, gibt es die so genannten Sanitizer. Wie weiter oben auch erwähnt, stellt sich nun die Frage, ob und wie Fehler effizient gefunden werden können. Für die Beantwortung dieser Frage, werden die Themen Delta Debugging und Continuous Testing behandelt. Anschließend wird das Werkzeug Valgrind, das überhaupt nicht effizient ist, näher erläutert. 3
4 2 Debugging 2.1 Was ist ein Bug? Ein Bug ist ein Programmfehler, welcher zur Laufzeit (erst bei der Ausführung) auftritt. Solche Fehler nennt man daher Laufzeitfehler. Nachdem ein Bug aufgetreten ist, zeigt das Programm ein fehlerhaftes Verhalten. Die Korrektheit des Programms ist gefährdet, indem zum Beispiel, falsche Werte übergeben werden. Möglicherweise wird die Ausführung des Programms komplett angehalten [2]. Eine Fehlermeldung könnte Hinweise auf die Ursache geben, jedoch kommt es oft vor, dass die Ursache nicht offensichtlich ist. Sobald die Ursache nicht offensichtlich ist und somit der Fehler nicht direkt gefunden und behoben werden kann, müssen Hilfsmittel wie Debugging benutzt werden. 2.2 Was ist Debugging? Sobald deutlich wird, dass ein Programm fehlerhaft ist, muss der Fehler zuerst lokalisiert werden. Es wird versucht den Teil des Programms zu finden, der für den Fehler verantwortlich ist. Nach der Fehlerlokalisierung muss der Programmierer nun den Fehler beheben, indem er den fehlerhaften Teil des Programms verändert. Dieser Vorgang wird auch Bugfixing genannt. Debugging besteht also aus den Aufgaben Fehlerlokalisierung und Bugfixing. Die Fehlerlokalisierung kann viel Zeit in Anspruch nehmen, denn wenn ein Programm hunderttausende Zeilen an Code hat, kann es etwas länger dauern bis der fehlerhafte Teil gefunden wird. Die zweite Aufgabe Bugfixing kann dagegen kompliziert werden, denn nachdem der fehlerhafte Teil gefixed wurde, können die Veränderungen, in diesem Teil, andere Fehler verursachen [2]. Im Allgemeinen gilt also, dass die Fehlerlokalisierung der zeitintensive und das Bugfixing der komplizierte Teil ist. Um den Aufwand gering zu halten, sollte möglichst früh, also in den ersten Phasen schon, mit dem Schreiben der Tests begonnen werden. Selbst kleinere Teile eines Programms sollten früh genug getestet werden, da in den späteren Phasen das Programm sehr komplex wird und somit auch die Fehleruntersuchung schwieriger wird [1]. 4
5 3 Speicherfehler in C In der Programmiersprache C erfolgt die Speicherverwaltung nicht, wie in anderen Sprachen (Java), automatisch. Daher können häufig Fehler in der Speicherverwaltung auftreten. Einige der typischen Speicherfehler werden in folgendem Abschnitt näher erläutert, damit diese Fehler dem Programmierer bekannt sind und vermieden werden können. 3.1 Nicht initialisierte Variablen In der Programmiersprache C muss eine Variable nicht zwingend initialisiert werden. Auch ohne die Initialisierung kann der Compiler übersetzen. So kann es beispielsweise passieren, dass der Programmierer entweder die Initialisierung einer lokalen Variable vergisst oder sogar davon ausgeht, dass ohne die Initialisierung der Wert 0 zugewiesen wird. Jedoch bekommt eine nicht initialisierte lokale Variable einen unbekannten beliebigen Wert. Durch solche Werte kann es dazu kommen, dass sich das Programm nicht mehr korrekt verhält, da falsche Werte übergeben wurden und falsche Ergebnisse zurückgeliefert werden können [3]. Vermieden kann dieser typische Fehler, indem die Initialisierung zur Angewohnheit wird und die Variablen immer automatisch von dem Programmierer initialisiert werden. Da aber auch Programmierer Fehler machen können und die Initialisierung vergessen können, gibt es zusätzlich auch Warnungen vom Compiler, die fehlende Initialisierungen aufzeigen. 3.2 Der Gültigkeitsbereich Es geht im Folgenden um die Erreichbarkeit und das Verschatten der Variablen. Variablen sind innerhalb ihres Anweisungsblockes erreichbar. Die Globalen Variablen werden außerhalb von allen Anweisungsblöcken definiert und sind somit in allen Anweisungsblöcken verfügbar. Die Verfügbarkeit von Variablen kann eingeschränkt werden, indem verschattet wird. Verschatten bedeutet, dass man die gleiche Bezeichnung, die schon für eine globale Variable verwendet wird, auch für eine lokale Variable benutzt. Innerhalb des Anweisungsblockes dieser lokalen Variable, ist nicht mehr die globale, sondern nur die lokale Variable erreichbar. 5
6 Bewusst verschatten verursacht keinen Fehler. Erst wenn der Programmierer den Überblick über die schon verwendeten Bezeichner verliert und unabsichtlich verschattet, wird das Programm nicht mehr korrekt laufen. Es können von den falschen Variablen Werte ausgelesen und falsche Variablen überschrieben werden. Verhindert kann dies durch die Wahl von Variablenbezeichnungen, die verständlich sind. Bezeichner wie x oder y sind ungünstig. Compiler können dies erkennen und geben Warnungen aus, die ernst genommen werden sollten. 3.3 Null-Pointer Wenn eine Allocation, also Reservierung vom Speicher, fehlschlägt, bekommen Pointer den Wert des Null-Pointers. Nach einem versuchten Zugriff auf einen Null-Pointer, bricht das Betriebssystem die Ausführung des Programms ab. Hierbei handelt es sich um einen Seitenfehler. Es wird versucht auf einen Speicher zuzugreifen, welcher nicht für dieses Programm zugelassen ist [4]. 3.4 Allocation Allocation bedeutet das Reservieren vom Speicher. Es gibt verschiedene Varianten, wie Speicher reseviert werden kann Memory Allocation: void *malloc(size_t size); Mit Memory Allocation (malloc) wird zur Laufzeit Speicherplatz reserviert. Mit dem Parameter size wird die Größe, die benötigt wird, in Byte übergeben. Der Rückgabewert ist ein void-zeiger oder ein null-zeiger, falls kein freier Speicher mehr zur Verfügung steht [5] Cleared Memory Allocation: void *calloc(size_t n, size_t size); Mit Cleared Memory Allocation (calloc) wird auch Speicher reserviert. Mit Memory Allocation wurde nach Bytes reserviert, mit calloc wird nach Elementen reserviert. Calloc und malloc unterscheiden sich dadurch, dass calloc die Speicherstellen mit 0 initialisiert, wobei malloc den Speicherinhalt unverändert lässt. Die Rückgabewerte sind im Endeffekt identisch [5]. 6
7 3.5 Speicherlecks Sobald ein Speicher alloziiert wurde und nicht mehr benötigt wird, ist es wichtig, dass es sofort wieder freigegeben wird. Wird regelmäßig Speicher reserviert, ohne ihn wieder freizugeben, kann es passieren, dass das System zum Erliegen kommt. Die unnötig reservierten und nicht wieder freigegebenen Speicherbereiche bleiben über die gesamte Laufzeit des Programms für das System unbrauchbar. Es kann also dazu kommen, dass der Speicher komplett belegt ist und die Daten auf die Festplatte ausgelagert werden müssen. Dieser Prozess kann relativ lange dauern [6]. Mit free kann der Speicher freigegeben werden, der mit malloc oder calloc reserviert wurde. Zudem darf der Speicher, der mit free freizugeben ist, nicht vorher freigegeben sein. Im folgenden Beispiel ist zu sehen, wie für die Variable test zuerst Speicher reserviert und wie dieser Speicher wieder freigegeben wird. 7
8 3.6 Zugriff nach Freigabe Nachdem ein Speicher mit free freigegeben wurde, besteht die Gefahr, dass trotzdem noch darauf zugegriffen wird. Dies stellt deswegen eine Gefahr dar, da dieser Speicher nicht mehr zur Verfügung steht und schon für andere Dinge in Verwendung sein kann. Zudem wird das Programm nicht unbedingt abstürzen, da der Speicher möglicherweise immer noch dem Programm gehört [7]. 3.7 Doppelte Freigabe Wenn der Programmierer vergisst, dass schon ein Speicher freigegeben wurde und es noch mal für denselben Speicher tut, entstehen unerwünschte Reaktionen. Das Resultat ist undefiniert [7]. In folgendem Beispiel ist zu sehen, wie ein Speicher freigegeben wird und versehentlich noch mal versucht wird, diesen wieder freizugeben. 4 Sanitizer Durch die Speicherfehler entstehen viele Sicherheitslücken. Daher ist es sehr wichtig diese Fehler zu finden. Es gibt verschiedene Ansätze, die Speicherfehler finden oder keine Speicherfehler erlauben. Das Projekt Softbound + CETS baut durch eine Erweiterung des Clang- Compilers von LLVM zusätzliche Checks in den generierten Code ein, um Zugriffe außerhalb zulässiger Speicherbereiche zu unterbinden Dieser Ansatz funktioniert zwar, jedoch sind die Performanceverluste hoch und lägen bei über 100 Prozent[8]. 8
9 4.1 AddressSanitizer Der AddressSanitizer ist ein Hilfsmittel um Speicherfehler zu finden [10]. Er ist ein Teil von Gcc und Clang. Während der Übersetzungszeit besteht die Möglichkeit den Code zu instrumentieren, damit dann zur Laufzeit Speicherfehler gefunden werden können. Fehler wie Use-after-free, Double-free, Memory-leak, etc. können gefunden werden. Der Speicherverbrauch sei bis zu dreimal so groß und der Performanceverlust läge etwa zwischen 70 und 100 Prozent. Dieser Ansatz ist weniger aufwändig als der vorherige, trotzdem ist der Performanceverlust zu hoch, da die Ausführungszeit sich ungefähr verdoppelt. Daher wird der AddressSanitizer hauptsächlich als Debugging-Tool genutzt[8]. 4.2 MemorySanitizer Der Memory Sanitizer ist in Clang integriert. Dieser kann Speicherfehler wie nicht initialisierte Variablen finden [11]. Auch dieser Sanitizer besteht aus einer Instrumentationskomponente, die den Code während der Übersetzungszeit instrumentiert und einer Laufzeitkomponente, die den Code zur Laufzeit auswertet und die speziellen Speicherfehler findet. Hier können sich die Ausführungszeit und der Speicherverbrauch zur Laufzeit bis zu verdreifachen[9]. 4.3 LeakSanitizer Der Leak Sanitizer kann zur Laufzeit Speicherlecks finden. Dieser Sanitizer kann auch mit dem Address Sanitizer kombiniert werden. Auch hier gilt aber, dass die Perfomance stark beeinträchtigt wird [12]. Zusammenfassend finden die Sanitizer viele der Speicherfehler. Der Memory Sanitizer jedoch sei jedoch noch in einem experimentellen Zustand und habe noch einige Fehler. Trotzdem sind die Sanitizer im Allgemeinen eine gute Hilfe um Speicherfehler zu finden. Der Nachteil ist jedoch, dass sie nicht effizient sind. Die Ausführungszeit und der Speicherverbrauch verdoppeln sich oder verdreifachen sich sogar. 9
10 5 Effizientes Fehlerfinden 5.1 Suchraum einschränken Damit nicht der gesamte Quellcode auf Fehler untersucht werden muss, sondern nur die Stellen in denen Änderungen vorgenommen wurden, werden Methoden wie Delta Debugging eingesetzt. Nehmen wir an, dass zwei Versionen eines Projektes mit entsprechenden funktionalen Tests vorliegen. Die Tests der älteren Version sind erfolgreich und einige Tests der neueren Version schlagen fehl. Dann kann die Abweichung beider Versionen, also das Delta bestimmt werden [13]. So stellt sich heraus welche der Anweisungen von Delta dafür verantwortlich sind, dass dieser Test fehlschlägt. Mit diesem Ansatz kann die zu untersuchenden Stellen eingeschränkt werden. 5.2 Delta Debugging Delta Debugging ist ein automatisches Verfahren, das die fehlerverursachenden Änderungen findet. Dabei wird schrittweise versucht, Regionen auszuschließen, die nicht für den Fehler verantwortlich sind [13]. In Folgendem wird Delta Debugging anhand eines Beispiels näher erläutert. Possible failure causes Set up first hypothesis Test first hypothesis Second hypothesis Third hypothesis Fourth hypothesis Abbildung 1: Das Prinzip des Delta Debuggings graphisch dargestellt. Durch das ständige Wiederholen der Iteration wird der zu suchende Raum kleiner. [Universität Saarland. 10
11 5.2.1 Beispiel 1 An diesem Beispiel wird die Funktionsweise des Delta Debuggers demonstriert. Die Mengen aller Änderungen sind durch die Zahlen von 1 bis 8 dargestellt. Zudem befindet sich in dem Beispiel eine c- Spalte, welche die Bezeichnungen für die Konfigurationen beinhaltet. Die Schritte 1 und 2 testen zwei Hälften (C₁ und C₂) der gesamten Änderungsmenge. Beide bestehen den Test. Dies bedeutet, dass der Fehler nur durch eine Kombination von Änderungen aus den Konfigurationen C₁ und C₂ hervorgerufen wird. Dies bedeutet, dass eine Interferenz vorliegen muss. Deshalb muss einer der beiden Teile fest sein und mit der anderen Hälfte der Algorithmus neugestartet werden. In diesem Fall ist C₂ fest. Nach Schritt 4 wird deutlich, dass der Fehler sich in dieser Änderungsmenge(3 8) befindet. So wird mit dieser Menge in Schritt 5 weiterverfahren. Die Änderungen 3 und 4 werden einzeln mit C₂ getestet und es stellt sich heraus, dass in der ersten Hälfte die Änderung 3 mit einer Änderung aus C₂ einen Fehler verursacht. Nun wird die Änderung in der zweiten Hälfe gesucht, die in Kombination mit der Änderung 3 den Fehler verursacht. Dafür wird die erste Hälfte festgehalten und mit der zweiten Hälfte weiterverfahren. In Schritt 8 bestehen die Änderungen 5 und 6 den Test nicht. So muss mit diesen beiden Änderungen weiterverfahren werden. Schließlich besteht in Schritt 10 die Änderung 6 nicht den Test und verursacht somit in Kombination mit der Änderung 3 einen Fehler. Mit diesem Beispiel wird unterstrichen, dass Delta Debugging ein fehlerlokalisierender Algorithmus ist. Die Änderungen, die nicht geändert wurden oder die die Tests bestanden haben, müssen nicht weiter berücksichtigt werden. Somit wird die Menge der Änderungen, die möglicherweise einen Fehler verursachen, kleiner. 11
12 5.3 Zeitnahes Fehlerfinden (Continuous Testing) In Entwicklungsumgebungen wie Eclipse findet die Kompilierung im Hintergrund statt. Während Funktionen oder sonstige Modifikationen am Quelltext vorgenommen werden, wird ständig, ohne dass explizit aufgefordert wird, der modifizierte Programmteil kompiliert. Dies bedeutet, dass dem Programmierer sofort die Programmfehler, die der Compiler erkennen kann, sichtbar gemacht werden. Dadurch erhöht sich auch die Qualität, da der Programmierer während der Programmierung schon auf Fehler und Warnungen aufmerksam gemacht wird. Somit ist auch der Prozess des Fehlerbehebens verkürzt, da der Programmierer während der Modifikation darauf reagieren kann, denn die logische Struktur des Problems muss nicht erneut gedanklich aufgebaut werden. Die Navigation zum Auftrittsort des Programmfehlers entfällt auch. Die Tests im Programm können manuell ausgeführt werden oder sie laufen ständig asynchron im Hintergrund. Die aktuelle Version des Quellcodes wird mit der letzten erfolgreichen Testdurchführung verglichen, damit nur die Tests wiederholt werden, die von einer Modifikation betroffen sind. Tests können auch automatisch priorisiert werden. Der Most-Recent-Failure-First-Ansatz hat sich als nützlich herausgestellt. Wenn ein Test aktuell fehlgeschlagen oder vor kurzem fehlgeschlagen ist, besteht die Gefahr, dass er wieder fehlschlägt. Deshalb sind solche Tests interessant für den Programmierer. Zusammenfassend ist Continuous Testing ein Plug- In, das Fehler vor allem zeitnah aufdeckt und die Tests stetig durchführt [14]. 6 Valgrind Mit dem Werkzeug Valgrind werden jegliche Arten von Speicherzugriffen zur Laufzeit überprüft. Dabei simuliert Valgrind einen kompletten Prozessor [15]. Er liest Binaries mit Debuginformationen ein, damit dann bei Fehlern auf die korrekte Quellcodezeile verwiesen werden kann. Diese werden in ein Zwischenformat übersetzt und Überprüfungsanweisungen in dieser Sprache hinzugefügt. Anschließend wird es dann wieder nach Maschinencode umgewandelt. Diese Aufwendigkeit macht sich auch bei der Performance deutlich bemerkbar. Die Ausführungszeit wächst auf ungefähr das 10 bis 50 fache an [2]. Dieser Performanceverlust kann nur dann akzeptabel sein, wenn es zu Testzwecken benutzt wird. 12
13 7 Zusammenfassung Die Sprache C ist wegen der manuellen Speicherverwaltung sehr beliebt. Dadurch kann Performance eines Programmes gesteigert werden. Jedoch können sehr viele Speicherfehler entstehen, die nicht schnell und leicht zu finden sind. Durch die Speicherfehler können Sicherheitslücken entstehen. Daher ist es wichtig diese Fehler zu finden und zu beheben. Das Werkzeug Valgrind kann zwar jegliche Arten von Speicherfehler finden, lässt aber die Ausführungszeit auf das 10 bis 50 fache wachsen. Eine Alternative sind die Sanitizer wie AddressSanitizer, LeakSanitizer, MemorySanitizer etc.. Diese können kombiniert werden und finden auch viele Arten der Speicherfehler. Bei den Sanitizer verdoppeln bis verdreifachen sich der Speicherverbrauch und die Ausführungszeit und sind somit effizienter als Valgrind. Trotzdem ist es ein starker Performanceverlust. Um nicht nur Speicherfehler, sondern auch andere Fehler finden zu können, gibt es Ansätze wie Delta Debugging und Continuous Testing. Delta Debugging und Continuous Testing schließen sich gegenseitig nicht aus. Denn Continuous Testing führt asymmetrisch die Tests im Hintergrund durch und findet die Fehler vor allem zeitnah. Delta Debugging verkleinert die bestehende Menge an fehlerverursachenden Anweisungen, indem der Suchraum mit dem Versuch- und Irrtum Prinzip eingegrenzt wird. 13
14 8 Literatur [1] Bugs und Fehlersuche, [2] Debugging, www2.in.tum.de/hp/file?fid=1239, [3] Nicht initialisierte Variablen, [4] Pointer, [5] Allocation, [6] Memory leaks, [7] Speicherverwaltung, [8] Pointer, [9] Vergleich unterschiedlicher Compiler,ftp://ftp.informatik.unistuttgart.de/pub/library/medoc.ustuttgart_fi/FACH-0198/FACH-0198.pdf, [10] AddressSanitizer, [11] MemorySanitizer, [12] LeakSanitizer, [13] Fehlerlokalisierung, [14] Martin Fowler. "Continuous Integration". [15] Valgrind, 14
Dynamische Speicherverwaltung
Dynamische Speicherverwaltung 1/ 23 Dynamische Speicherverwaltung Tim Dobert 17.05.2013 Dynamische Speicherverwaltung 2/ 23 Gliederung 1 Allgemeines zur Speichernutzung 2 Ziele und Nutzen 3 Anwendung in
Typische Speicherfehler in C
Typische Speicherfehler in C Thorsten Ploß Informatik Universität Hamburg Proseminar: C-Grundlagen und Konzepte 17.05.2013 1 / 13 Inhaltsverzeichnis Einleitung Klassische Speicherverwaltung - Fehlerquellen
Dynamisches Speichermanagement
Dynamisches Speichermanagement Proseminar C-Programmierung - Grundlagen und Konzepte Timo Minartz [email protected] Wissenschaftliches Rechnen Fachbereich Informatik Universität Hamburg
C/C++-Programmierung
1 C/C++-Programmierung Speicherverwaltung, 0, const Sebastian Hack Christoph Mallon (hack mallon)@cs.uni-sb.de Fachbereich Informatik Universität des Saarlandes Wintersemester 2009/2010 2 Speicherverwaltung
Crashkurs C++ - Teil 1
Crashkurs C++ - Teil 1 Intro Speicherverwaltung Variablen, Pointer, Referenzen Felder statische & dynamische Allozierung Birgit Möller & Denis Williams AG Bioinformatik & Mustererkennung Institut für Informatik
Übungspaket 29 Dynamische Speicherverwaltung: malloc() und free()
Übungspaket 29 Dynamische Speicherverwaltung malloc() und free() Übungsziele Skript In diesem Übungspaket üben wir das dynamische Alloziieren 1. und Freigeben von Speicherbereichen 2. von Zeichenketten
Einführung in die Programmierung zusammengesetzte Datentypen, dynamischer Speicher
Einführung in die Programmierung zusammengesetzte Datentypen, dynamischer Speicher Arvid Terzibaschian 1 Zusammengesetzte Datentypen 2 Wozu zusammengesetzte Datentypen? Anforderung: Sie sollen ein Kundenverzeichnis
Vorlesung Programmieren
Vorlesung Programmieren Speicherverwaltung und Parameterübergabe Prof. Dr. Stefan Fischer Institut für Telematik, Universität zu Lübeck http://www.itm.uni-luebeck.de/people/fischer Gültigkeitsbereich von
9 Zeiger (Pointer). Dynamischer Speicher
9 Zeiger (Pointer). Dynamischer Speicher Jörn Loviscach Versionsstand: 25. September 2013, 18:07 Die nummerierten Felder sind absichtlich leer, zum Ausfüllen beim Ansehen der Videos: http://www.j3l7h.de/videos.html
Programmieren in C. Speicher anfordern, Unions und Bitfelder. Prof. Dr. Nikolaus Wulff
Programmieren in C Speicher anfordern, Unions und Bitfelder Prof. Dr. Nikolaus Wulff Vergleich: Felder und Strukturen Felder müssen Elemente vom selben Typ enthalten. Strukturen können Elemente unterschiedlichen
Dynamische Speicherverwaltung
Dynamische Speicherverwaltung Tim Dobert 17.05.2013 Inhaltsverzeichnis 1 Allgemeines zur Speichernutzung 2 2 Ziel und Nutzen 2 3 Anwendung in C 2 3.1 malloc............................... 3 3.2 calloc...............................
Speicherverwaltung in C
Speicherverwaltung in C Tobias Gutzmann, Le Xuan Khanh, Robert Hartmann 19.04.2005 Typeset by FoilTEX Inhalt Übersicht der wichtigsten Befehle malloc, free, realloc alloca, obstack, brk Speicherverwaltung
Carlos Santos. Fachbereich Informatik Fakultät für Mathematik, Informatik und Naturwissenschaften. Universität Hamburg
Universität Hamburg Proseminar: Werkzeuge für das wissenschaftliche Schreiben Fachbereich Informatik Fakultät für Mathematik, Informatik und Naturwissenschaften Überblick Einführung - Geschichte Einstellungen
Effizientes Memory Debugging in C/C++
Effizientes Memory Debugging in C/C++ Adam Szalkowski Embedded Computing Conference 2014 Ursachen/ Symptome Debugging Tools Ursachen / Symptome Was habe ich falsch gemacht? Was kann denn passieren im schlimmsten
Übersicht. Speichertypen. Speicherverwaltung und -nutzung. Programmieren in C
Übersicht Speichertypen Speicherverwaltung und -nutzung Speichertypen Beim Laden eines Programms in den Speicher (Programmausführung) kommen 3 verschiedene Speicherbereiche zum Einsatz: Text Segment (Code
U4-1 Aufgabe 3: einfache malloc-implementierung
U4 3. Übung U4 3. Übung Besprechung der Aufgabe 2: wsort Aufgabe 3: malloc-implementierung Ziele der Aufgabe Zusammenhang zwischen "nacktem Speicher" und typisierten bereichen verstehen Funktion aus der
Algorithmen und Datenstrukturen
Algorithmen und Datenstrukturen Dipl. Inform. Andreas Wilkens [email protected] Überblick Grundlagen Definitionen Eigene Entwicklungen Datenstrukturen Elementare Datentypen Abstrakte Datentypen Elementare
fungen Debugging Boris Tripolskij
Werkzeuggestützte tzte Softwareprüfungen fungen Debugging Boris Tripolskij Gliederung Motivation für Debugging Aufbau des Debuggers in Eclipse Arten von Debugging Tools Fehlerarten Delta Debugging Vorführung
Programmieren in Haskell Debugging
Programmieren in Haskell Debugging Peter Steffen Universität Bielefeld Technische Fakultät 30.01.2009 1 Programmieren in Haskell Debugger Definition laut Wikipedia: Ein Debugger (von engl. bug im Sinne
2. Programmierung in C
2. Programmierung in C Inhalt: Überblick über Programmiersprachen, Allgemeines zur Sprache C C: Basisdatentypen, Variablen, Konstanten, Operatoren und Ausdrücke Anweisungen und Kontrollstrukturen (Steuerfluss)
PROGRAMMIEREN MIT C. }, wird kompiliert mit dem Befehl. (-o steht für output) und ausgeführt mit dem Befehl
PROGRAMMIEREN MIT C Allgemeine hinweise Alles was hier beschrieben wird, soll auch ausprobiert werden. Warum C? Weil die coolen Dinge mit C am einfachsten gehen. Das werden wir in den folgenden Übungen
Übungspaket 23 Mehrdimensionale Arrays
Übungspaket 23 Mehrdimensionale Arrays Übungsziele: Skript: Deklaration und Verwendung mehrdimensionaler Arrays Kapitel: 49 Semester: Wintersemester 2016/17 Betreuer: Kevin, Matthias, Thomas und Ralf Synopsis:
Beispiel. Problem: mehrteilige Nachnamen (von Goethe, Mac Donald, Di Caprio)
Beispiel Beispiel: Namensliste konvertieren (Karl Egon Meier Meier, Karl Egon). s/(.*) (.*)/$2, $1/; Problem: mehrteilige Nachnamen (von Goethe, Mac Donald, Di Caprio) s/(.*) (.*)/$2, $1/; s/(.*) ([a-z]+
Funktionen, Zeiger und Arrays in C Software Entwicklung 1
Funktionen, Zeiger und Arrays in C Software Entwicklung 1 Annette Bieniusa, Mathias Weber, Peter Zeller 1 Funktionen Mit Hilfe von Funktionen kann man (wie mit Prozeduren bzw. Methoden in Java) eine Problemstellung
C- Kurs 08 Zeiger. Dipl.- Inf. Jörn Hoffmann leipzig.de. Universität Leipzig Ins?tut für Informa?k Technische Informa?
C- Kurs 08 Dipl.- Inf. Jörn Hoffmann jhoffmann@informa?k.uni- leipzig.de Universität Leipzig Ins?tut für Informa?k Technische Informa?k Überblick Datentyp zur Verwaltung von Adressen (auf Speicherplätze)
Grundlagen der OO- Programmierung in C#
Grundlagen der OO- Programmierung in C# Technische Grundlagen 1 Dr. Beatrice Amrhein Überblick Visual Studio: Editor und Debugging Die Datentypen Methoden in C# Die Speicherverwaltung 2 Visual Studio 3
Dynamischer Speicher
Dynamischer Speicher C-Kurs 2012, 3. Vorlesung Tino Kutschbach [email protected] http://wiki.freitagsrunde.org 13. September 2012 This work is licensed under the Creative Commons Attribution-ShareAlike
Typische Speicherfehler in C
Typische Speicherfehler in C Thorsten Ploß Informatik Universität Hamburg Proseminar: C-Grundlagen und Konzepte 15. Juli 2013 1 Inhaltsverzeichnis 2 1 Einleitung Dank der Optimierung auf Geschwindigkeit
Übungen zu Systemprogrammierung 1 (SP1)
Übungen zu Systemprogrammierung 1 (SP1) Ü1-2 Speicherverwaltung Andreas Ziegler, Stefan Reif, Jürgen Kleinöder Lehrstuhl für Informatik 4 Verteilte Systeme und Betriebssysteme Friedrich-Alexander-Universität
Betriebssysteme. Tafelübung 4. Speicherverwaltung. Olaf Spinczyk.
Betriebssysteme Tafelübung 4. Speicherverwaltung http://ess.cs.tu-dortmund.de/de/teaching/ss217/bs/ Olaf Spinczyk [email protected] http://ess.cs.tu-dortmund.de/~os AG Eingebettete Systemsoftware
Das diesem Dokument zugrundeliegende Vorhaben wurde mit Mitteln des Bundesministeriums für Bildung und Forschung unter dem Förderkennzeichen
Das diesem Dokument zugrundeliegende Vorhaben wurde mit Mitteln des Bundesministeriums für Bildung und Forschung unter dem Förderkennzeichen 16OH21005 gefördert. Die Verantwortung für den Inhalt dieser
6. Zeiger Allgemeines Definition eines Zeigers
6. Zeiger www.c-programme.de Stefan Thiemert Kapitel 6 - Seite 1 von 6 6. 1. Allgemeines Zeiger spielen in der Programmierung eine wichtige Rolle. Sie sind wichtig, bei der Arbeit mit Arrays und Funktionen.
Betriebssysteme. Agenda. Tafelübung 4. Speicherverwaltung. Olaf Spinczyk.
Betriebssysteme Tafelübung 4. Speicherverwaltung http://ess.cs.tu-dortmund.de/de/teaching/ss217/bs/ Olaf Spinczyk [email protected] http://ess.cs.tu-dortmund.de/~os AG Eingebettete Systemsoftware
Erster Bug: eine Motte
SOFTWAREFEHLER Der erste Bug Erster Bug: eine Motte Der Begriff Bug (deutsch: Motte) stammt aus dem Jahre 1945, als Ingenieure in einem Schaltrelais eines Computers (Harvard Mark II-System) eine Motte
Programmiersprache 1 (C++) Prof. Dr. Stefan Enderle NTA Isny
Programmiersprache 1 (C++) Prof. Dr. Stefan Enderle NTA Isny 9. Zeiger Arbeitsspeicher / Adressen Der Arbeitsspeicher des Computers (RAM) besteht aus einem Feld von Speicherzellen, beginnend bei Adresse
C++ - Variablen: Gültigkeit - Sichtbarkeit
C++ - Variablen: Gültigkeit - Sichtbarkeit Reiner Nitsch 8417 [email protected] Attribute von Variablen und Funktionen Attribute von Variablen sind Name (name), Typ (type), Wert (value) Attribute von
Algorithmen und Datenstrukturen
Algorithmen und Datenstrukturen Dynamische Datenobjekte Pointer/Zeiger, Verkettete Liste Eigene Typdefinitionen 1 Zeigeroperatoren & und * Ein Zeiger ist die Speicheradresse irgendeines Objektes. Eine
Vorsemesterkurs Informatik
Vorsemesterkurs Informatik Programmieren und Programmiersprachen SoSe 2012 Stand der Folien: 26. März 2012 Übersicht Programme und Programmiersprachen Haskell 1 Programme und Programmiersprachen 2 Haskell
Programmiertechnik. Teil 4. C++ Funktionen: Prototypen Overloading Parameter. C++ Funktionen: Eigenschaften
Programmiertechnik Teil 4 C++ Funktionen: Prototypen Overloading Parameter C++ Funktionen: Eigenschaften Funktionen (Unterprogramme, Prozeduren) fassen Folgen von Anweisungen zusammen, die immer wieder
Übung zu Grundlagen der Betriebssysteme. 13. Übung 22.01.2012
Übung zu Grundlagen der Betriebssysteme 13. Übung 22.01.2012 Aufgabe 1 Fragmentierung Erläutern Sie den Unterschied zwischen interner und externer Fragmentierung! Als interne Fragmentierung oder Verschnitt
Institut für Computational Science Prof. Dr. H. Hinterberger. Praxismodul 1. Einführung in die Programmierung Erste Programme
Institut für Computational Science Prof. Dr. H. Hinterberger Praxismodul 1 Einführung in die Programmierung Erste Programme Einführung in die Programmierung 2 Institut für Computational Science, ETH Zürich,
Inhalt. 4.5 Arbeit mit Zeigern (engl. Pointer)
Inhalt Inhalt: 4. Programmiersprache C 4.1 Programmaufbau in C 4.2 Basisdatentypen und einfache Anweisungen 4.3 Steuerfluss-Konstrukte 4.4 Arbeit mit indizierten Größen (Felder) 4.5 Arbeit mit Zeigern
Vom Testkonzept zu JUnit
Testen und Testkonzept Dipl.-Inf. (FH) Christopher Olbertz 2. Dezember 2014 Testen und Testkonzept Warum testen? Wichtig, obwohl bei Programmierern unbeliebt Stellt weitgehend korrekte Funktionsweise eines
FACHHOCHSCHULE MANNHEIM
für Java-Programmierer Der Präprozessor Prof. Dr. Wolfgang Schramm FACHHOCHSCHULE MANNHEIM Hochschule für Technik und Gestaltung Präprozessor Ist dem Compiler vorgeschaltet ( Prä -). Spezielle Anweisungen
Welche Informatik-Kenntnisse bringen Sie mit?
Welche Informatik-Kenntnisse bringen Sie mit? So gehen Sie vor! Lösen Sie die Aufgaben der Reihe nach von 1 bis 20, ohne das Lösungsblatt zur Hilfe zu nehmen. Der Schwierigkeitsgrad der Aufgaben nimmt
Übungspaket 23 Mehrdimensionale Arrays
Übungspaket 23 Mehrdimensionale Arrays Übungsziele: Skript: Deklaration und Verwendung mehrdimensionaler Arrays Kapitel: 49 Semester: Wintersemester 2016/17 Betreuer: Kevin, Matthias, Thomas und Ralf Synopsis:
Hydroinformatik I: Referenzen und Zeiger
Hydroinformatik I: Referenzen und Zeiger Prof. Dr.-Ing. habil. Olaf Kolditz 1 Helmholtz Centre for Environmental Research UFZ, Leipzig 2 Technische Universität Dresden TUD, Dresden Dresden, 06. Januar
Was ist ein Profiler?
Profiling Was ist ein Profiler? (Theorie) Invasives Profiling Nichtinvasives Profiling Profiling in der Praxis gprof, gcov OProfile valgrind/callgrind Intel VTune Was ist ein Profiler? Analyse des Laufzeitverhaltens
Vom Leichtesten zum Schwersten Sortieralgorithmen
Aktivität 7 Vom Leichtesten zum Schwersten Sortieralgorithmen Zusammenfassung Häufig verwendet man Computer dazu Listen von Elementen in eine bestimmte Ordnung zu bringen. So kann man beispielsweise Namen
Modul Entscheidungsunterstützung in der Logistik. Einführung in die Programmierung mit C++ Übung 1
Fakultät Verkehrswissenschaften Friedrich List, Professur für Verkehrsbetriebslehre und Logistik Modul Entscheidungsunterstützung in der Logistik Einführung in die Programmierung mit C++ Übung 1 SS 2016
Einleitung Entwicklung in C Hello-World! Konstrukte in C Zusammenfassung Literatur. Grundlagen von C. Jonas Gresens
Grundlagen von C Jonas Gresens Proseminar C Grundlagen und Konzepte Arbeitsbereich Wissenschaftliches Rechnen Fachbereich Informatik Fakultät für Mathematik, Informatik und Naturwissenschaften Universität
Objektorientierte Programmierung. Kapitel 22: Aufzählungstypen (Enumeration Types)
Stefan Brass: OOP (Java), 22. Aufzählungstypen 1/20 Objektorientierte Programmierung Kapitel 22: Aufzählungstypen (Enumeration Types) Stefan Brass Martin-Luther-Universität Halle-Wittenberg Wintersemester
Felder, Zeiger und Adreßrechnung
Felder, Zeiger und Adreßrechnung Felder bestehen aus Variablen eines einzigen Datentyps. Bisher kennen wir eindimensionale Felder. In C sind Felder mit beliebigen Dimensionen möglich. Unsere räumliche
Grundlagen der Programmentwicklung
Informatik für Elektrotechnik und Informationstechnik Benedict Reuschling [email protected] Hochschule Darmstadt Fachbereich Informatik WS 2013/14 Über C++ Über C++ C++ ist eine in der Industrie
8. Referenzen und Zeiger
8. Referenzen und Zeiger Motivation Variable werden in C++ an speziellen Positionen im Speicher abgelegt. An jeder Position befindet sich 1 Byte. Sie sind durchnummeriert beginnend bei 0. Diese Positionen
Konzepte von Betriebssystem-Komponenten. Programmstart & dynamische Bibliotheken SS 05. Wladislaw Eckhardt.
Proseminar KVBK Programmstart dynamische Bibliotheken Konzepte von Betriebssystem-Komponenten Programmstart & dynamische Bibliotheken SS 05 Wladislaw Eckhardt [email protected] 1 1 Einleitung 1.1 Problematik
Programmieren in C. Eine Einführung in die Programmiersprache C. Prof. Dr. Nikolaus Wulff
Programmieren in C Eine Einführung in die Programmiersprache C Prof. Dr. Nikolaus Wulff Agenda Elementare Einführung C Programm Syntax Datentypen, Variablen und Konstanten Operatoren und Ausdrücke Kontrollstrukturen
Programmierung mit C Modularisierung von Programmen. Präprozessor-Anweisungen nutzen.
Programmierung mit C Modularisierung von Programmen. Präprozessor-Anweisungen nutzen. Modularisierung Zerlegung eines Programms in überschaubare Einheiten Die einzelnen Einheiten werden als Modul bezeichnet.
MÖGLICHKEITEN UND GRENZEN IN DER DYNAMISCHEN CODEANALYSE VON C++ SOFTWARE. Von Matthias Neumann
MÖGLICHKEITEN UND GRENZEN IN DER DYNAMISCHEN CODEANALYSE VON C++ SOFTWARE Von Matthias Neumann 19.01.2015 2/35 Inhaltsangabe Einleitung Ausprägungen der dynamischen Codeanalyse Debugging Logging Testing
einlesen n > 0? Ausgabe Negative Zahl
1 Lösungen Kapitel 1 Aufgabe 1.1: Nassi-Shneiderman-Diagramm quadratzahlen Vervollständigen Sie das unten angegebene Nassi-Shneiderman-Diagramm für ein Programm, welches in einer (äußeren) Schleife Integer-Zahlen
F Zeiger, Felder und Strukturen in C
F Zeiger, Felder und Strukturen in C F Zeiger, Felder und Strukturen in C F.1 Zeiger(-Variablen) 1 Einordnung Konstante: Bezeichnung für einen Wert a 0110 0001 Variable: Bezeichnung eines Datenobjekts
Schachtelung der 2. Variante (Bedingungs-Kaskade): if (B1) A1 else if (B2) A2 else if (B3) A3 else if (B4) A4 else A
2.4.6. Kontrollstrukturen if-anweisung: Bedingte Ausführung (Verzweigung) 2 Varianten: if (Bedingung) Anweisung (Anweisung = einzelne Anweisung oder Block) Bedeutung: die Anweisung wird nur ausgeführt,
11. Die PC-Schnittstelle
PC-Schnittstelle Funktion -1. Die PC-Schnittstelle.1. Funktion Die folgenden Angaben gelten ohne Einschränkung für den PC, PC-XT, PC-AT, AT-386, AT-486 und kompatible Rechner. Sie sind nur für jene interessant,
Einstieg in die Informatik mit Java
1 / 27 Einstieg in die Informatik mit Java Klassen als Datenstrukturen Gerd Bohlender Institut für Angewandte und Numerische Mathematik Gliederung 2 / 27 1 Überblick: Klassen als Datenstruktur 2 Vereinbarung
Systeme I: Betriebssysteme Kapitel 8 Speicherverwaltung
Systeme I: Betriebssysteme Kapitel 8 Speicherverwaltung Version 21.12.2016 1 Inhalt Vorlesung Aufbau einfacher Rechner Überblick: Aufgabe, Historische Entwicklung, unterschiedliche Arten von Betriebssystemen
CPU-Caches. Christian Duße. Seminar Effiziente Programmierung in C
CPU-Caches Christian Duße Seminar Effiziente Programmierung in C Arbeitsbereich Wissenschaftliches Rechnen Fachbereich Informatik Fakultät für Mathematik, Informatik und Naturwissenschaften Universität
Projektdokumentation
Projektdokumentation Schachspiel mit JavaScript Daniel Mockenhaupt Klasse 10b Projektdokumentation: Schachspiel mit JavaScript Seite 1 Einführung Ziel dieser Projektarbeit soll die Erstellung eines Schachspiels
(a) Wie unterscheiden sich synchrone und asynchrone Unterbrechungen? (b) In welchen drei Schritten wird auf Unterbrechungen reagiert?
SoSe 2014 Konzepte und Methoden der Systemsoftware Universität Paderborn Fachgebiet Rechnernetze Präsenzübung 2 2014-04-28 bis 2014-05-02 Aufgabe 1: Unterbrechungen (a) Wie unterscheiden sich synchrone
Java Einführung Methoden. Kapitel 6
Java Einführung Methoden Kapitel 6 Inhalt Deklaration und Aufruf von Methoden Lokale und globale Namen (Bezeichner) Sichtbarkeit und Lebensdauer von Variablen in Methoden Überladen von Methoden 2 Methoden
HSR Rapperswil 2001 Markus Rigling. Programmieren: Vererbung. 1 Variante 2
HSR Rapperswil 2001 Markus Rigling Programmieren: Vererbung 1 Variante 2 Inhaltsverzeichnis: 1. Was ist Vererbung...3 2. Anwendung...3 3. Realisierung...3 4. Vorgehensweise zur Erstellung einer Kind-Klasse...3
C++ Teil 6. Sven Groß. 27. Mai Sven Groß (IGPM, RWTH Aachen) C++ Teil Mai / 14
C++ Teil 6 Sven Groß 27. Mai 2016 Sven Groß (IGPM, RWTH Aachen) C++ Teil 6 27. Mai 2016 1 / 14 Themen der letzten Vorlesung Musterlösung A2 Wdh.: Zeiger und Felder Kopieren von Feldern Dynamische Speicherverwaltung
Einstieg in die Informatik mit Java
1 / 20 Einstieg in die Informatik mit Java Rekursion Gerd Bohlender Institut für Angewandte und Numerische Mathematik Gliederung 2 / 20 1 Überblick 2 Rekursion 3 Rekursive Sortieralgorithmen 4 Backtracking
Zum Aufwärmen nocheinmal grundlegende Tatsachen zum Rechnen mit reelen Zahlen auf dem Computer. Das Rechnen mit Gleitkommazahlen wird durch den IEEE
Zum Aufwärmen nocheinmal grundlegende Tatsachen zum Rechnen mit reelen Zahlen auf dem Computer. Das Rechnen mit Gleitkommazahlen wird durch den IEEE 754 Standard festgelegt. Es stehen sogenannte einfach
Modul Entscheidungsunterstützung in der Logistik. Einführung in die Programmierung mit C++ Übung 2
Fakultät Verkehrswissenschaften Friedrich List, Professur für Verkehrsbetriebslehre und Logistik Modul Entscheidungsunterstützung in der Logistik Einführung in die Programmierung mit C++ Übung 2 SS 2016
Kurzeinführung in C99
Kurzeinführung in C99 Institut für Numerische Simulation Rheinische Friedrich-Wilhelms-Universität Bonn Oktober 2013 Überblick 1 Compiler und Editoren - Was wird benötigt um ein Programm zu erstellen 2
Tools zur Programmierung mit C Software Entwicklung 1
Tools zur Programmierung mit C Software Entwicklung 1 Annette Bieniusa, Mathias Weber, Peter Zeller Inhaltsverzeichnis 1 Compiler 1 1.1 Installation.................................. 2 1.1.1 Installation
Advanced Programming in C
Advanced Programming in C Pointer und Listen Institut für Numerische Simulation Rheinische Friedrich-Wilhelms-Universität Bonn Oktober 2013 Überblick 1 Variablen vs. Pointer - Statischer und dynamischer
C++ Teil 5. Sven Groß. 13. Mai Sven Groß (IGPM, RWTH Aachen) C++ Teil Mai / 18
C++ Teil 5 Sven Groß 13. Mai 2016 Sven Groß (IGPM, RWTH Aachen) C++ Teil 5 13. Mai 2016 1 / 18 Themen der letzten Vorlesung Funktionen Funktionsüberladung, Signatur Rekursion const-deklaration Referenzen
Grundlagen und Konzepte von C Datenstrukturen
Grundlagen und Konzepte von C Datenstrukturen Ausarbeitung von Andreas Gadelmaier Proseminar C Grundlagen und Konzepte Arbeitsbereich Wissenschaftliches Rechnen Fachbereich Informatik Fakultät für Mathematik,
Verschlüsseln eines Bildes. Visuelle Kryptographie. Verschlüsseln eines Bildes. Verschlüsseln eines Bildes
Verschlüsseln eines Bildes Visuelle Kryptographie Anwendung von Zufallszahlen Wir wollen ein Bild an Alice und Bob schicken, so dass Alice allein keine Information über das Bild bekommt Bob allein keine
Kapitel. Platzhalter. Was sind Platzhalter?
Kapitel 3 Was sind? sind ganz wichtige Elemente bei der Programmierung. Alle Programme, die du schon kennst (wie beispielsweise die Textverarbeitung WORD oder ein Programm zum Verschicken von E-Mails),
Einführung in die Programmierung WS 2009/10. Übungsblatt 5: Typen, Variablen und einfache Methoden in Java
Ludwig-Maximilians-Universität München München, 20.11.2009 Institut für Informatik Prof. Dr. Christian Böhm Annahita Oswald, Bianca Wackersreuther Einführung in die Programmierung WS 2009/10 Übungsblatt
Multidimensionale Arrays in C
Multidimensionale Arrays in C Florian Wilkens Arbeitsbereich Wissenschaftliches Rechnen Fachbereich Informatik Fakultät für Mathematik, Informatik und Naturwissenschaften Universität Hamburg 21.11.2013
Freispeicherverwaltung Martin Wahl,
Freispeicherverwaltung Martin Wahl, 17.11.03 Allgemeines zur Speicherverwaltung Der physikalische Speicher wird in zwei Teile unterteilt: -Teil für den Kernel -Dynamischer Speicher Die Verwaltung des dynamischen
OpenCL. Programmiersprachen im Multicore-Zeitalter. Tim Wiersdörfer
OpenCL Programmiersprachen im Multicore-Zeitalter Tim Wiersdörfer Inhaltsverzeichnis 1. Was ist OpenCL 2. Entwicklung von OpenCL 3. OpenCL Modelle 1. Plattform-Modell 2. Ausführungs-Modell 3. Speicher-Modell
Zeiger und dynamischer Speicher
Informatik für Elektrotechnik und Informationstechnik Benedict Reuschling [email protected] Hochschule Darmstadt Fachbereich Informatik WS 2013/14 Zuletzt aktualisiert: 09.12.2013, 07:49 Uhr
Institut für Informatik
Technische Universität München Institut für Informatik Lehrstuhl für Computer Graphik & Visualisierung WS 2010 Praktikum: Grundlagen der Programmierung Aufgabenblatt 4 Prof. R. Westermann, A. Lehmann,
