Zeiger in C und C++ Zeiger in Java und C/C++

Ähnliche Dokumente
Zeiger in C und C++ Zeiger in Java und C/C++

Zeiger, Arrays und Strings in C und C++

Programmierung mit C Zeiger

F Zeiger, Felder und Strukturen in C

5.4 Arrays. Oft müssen viele Werte gleichen Typs gespeichert werden. Idee: Lege sie konsekutiv ab! Greife auf einzelne Werte über ihren Index zu!

Vorlesung Programmieren

Dynamische Speicherverwaltung

C++ Teil 5. Sven Groß. 13. Mai Sven Groß (IGPM, RWTH Aachen) C++ Teil Mai / 18

Grundlagen der Informatik 11. Zeiger

Crashkurs C++ - Teil 1

Algorithmen und Datenstrukturen

2. Programmierung in C

8. Referenzen und Zeiger

Angewandte Mathematik und Programmierung

C++ Teil 6. Sven Groß. 27. Mai Sven Groß (IGPM, RWTH Aachen) C++ Teil Mai / 14

Programmieren in C. Speicher anfordern, Unions und Bitfelder. Prof. Dr. Nikolaus Wulff

C/C++-Programmierung

Zeiger (engl. Pointer)

U8 7. Übung U8 7. Übung

C++ Teil 5. Sven Groß. 8. Mai IGPM, RWTH Aachen. Sven Groß (IGPM, RWTH Aachen) C++ Teil 5 8. Mai / 16

Zeiger & Co. Verwendung und Zeigerarithme5k. thorsten möller - informa5k.unibas.ch/lehre/fs13/cs109/03- c++- zeiger.pdf. Strukturen. enum.

Zeiger. C-Kurs 2012, 2. Vorlesung. Tino Kutschbach 10.

Inhalt. 4.5 Arbeit mit Zeigern (engl. Pointer)

Grundlagen der Programmiersprache C für Studierende der Naturwissenschaften

Dynamischer Speicher

Pointer und Arrays. INE1, Montag M. Thaler, Office TG208. ZHAW, M. Thaler, K. Rege, G.

RO-Tutorien 3 / 6 / 12

C++ - Einführung in die Programmiersprache Zeiger, Referenzen und Strukturen. Leibniz Universität IT Services Anja Aue

6 ZEIGER UND REFERENZEN - ALLGEMEINES

Teil 5: Zeiger, Felder, Zeichenketten Gliederung

Programmiersprache 1 (C++) Prof. Dr. Stefan Enderle NTA Isny

Kapitel 6: Dynamische Speicherverwaltung

Praxisorientierte Einführung in C++ Lektion: "Dynamische Speicherverwaltung"

Einführung in die Programmiersprache C

Übersicht. Speichertypen. Speicherverwaltung und -nutzung. Programmieren in C

U3 3. Übung U3 3. Übung. Systemnahe Programmierung in C Übungen Moritz Strübe Universität Erlangen-Nürnberg Informatik 4, 2009 U3.fm

Arrays,Strings&Pointer in C/C++

9 Zeiger (Pointer). Dynamischer Speicher

5.1 Mehr Basistypen. (Wie viele Werte kann man mit n Bit darstellen?)

6. Zeiger Allgemeines Definition eines Zeigers

Dynamische Speicherverwaltung

C++ Notnagel. Ziel, Inhalt. Programmieren in C++

RO-Tutorien 15 und 16

Variablen. Deklaration: «Datentyp» «Variablenname» Datentyp bestimmt Größe in Bytes: sizeof Beispiel: long int v; Größe: 4 Bytes

Übungspaket 29 Dynamische Speicherverwaltung: malloc() und free()

RO-Tutorien 17 und 18

Betriebssysteme. Tafelübung 4. Speicherverwaltung. Olaf Spinczyk.

Betriebssysteme. Agenda. Tafelübung 4. Speicherverwaltung. Olaf Spinczyk.

Zeiger und dynamischer Speicher

Programmieren in C++ Überladen von Methoden und Operatoren

Pointer. Variablen. Pointer. Ein elementares Beispiel. Pointer in C

Einleitung Typsystem Typisierung Zusammenfassung Literatur. Typisierung. Effiziente Programmierung. Thomas Schnieders

GI Vektoren

Software Entwicklung 1

Modellierung und Programmierung 1

6 Speicherorganisation

Dr. Monika Meiler. Inhalt

Zeiger: Der Adressoperator &

Einführung in die Programmierung zusammengesetzte Datentypen, dynamischer Speicher

Programmieren in Java

Programmierkurs C++ Datenstrukturen Seite 1

C++ - Objektorientierte Programmierung Konstante und statische Elemente

Institut für Programmierung und Reaktive Systeme. Java 2. Markus Reschke

Einführung in die Programmierung II. 5. Zeiger

Tutorium Rechnerorganisation

C- Kurs 08 Zeiger. Dipl.- Inf. Jörn Hoffmann leipzig.de. Universität Leipzig Ins?tut für Informa?k Technische Informa?

10 Die Programmiersprache C99: Zusammenfassung

Heap vs. Stack vs. statisch. 6 Speicherorganisation. Beispiel Statische Variablen. Statische Variablen

Zeiger in C. Thomas Mechelke August 2011

Dynamische Datentypen

Informatik 1 ( ) D-MAVT F2010. Schleifen, Felder. Yves Brise Übungsstunde 5

Die Sprache C# Datentypen, Speicherverwaltung Grundelemente der Sprache. Dr. Beatrice Amrhein

Programmiertechnik. Teil 4. C++ Funktionen: Prototypen Overloading Parameter. C++ Funktionen: Eigenschaften

Heap vs. Stack vs. statisch. 6 Speicherorganisation. Beispiel Statische Variablen. Statische Variablen

Programmierkurs C++ Variablen und Datentypen

Die Programmiersprache C99: Zusammenfassung

Einführung in den Einsatz von Objekt-Orientierung mit C++ I

einlesen n > 0? Ausgabe Negative Zahl

Betriebssysteme, Rechnernetze und verteilte Systeme 1. Crashkurs C (2)

INE1 Speicherverwaltung und zweidimensionale Arrays. Speicherorganisation Dynamischer Speicher in C Zweidimensionale Arrays

Kapitel 4. Programmierkurs. Datentypen. Arten von Datentypen. Wiederholung Kapitel 4. Birgit Engels, Anna Schulze WS 07/08

Einführung in die Programmierung Arrays, Zeiger, Strings. Arvid Terzibaschian

Grundlagen der Informatik 2. Operatoren

Funktionen, Zeiger und Arrays in C Software Entwicklung 1

1. Referenzdatentypen: Felder und Strings

1. Referenzdatentypen: Felder und Strings. Referenz- vs. einfache Datentypen. Rückblick: Einfache Datentypen (1) 4711 r

Dynamische Speicherverwaltung

Propädeutikum. Dipl.-Inf. Frank Güttler

Programmiertechnik 1. Unit 9: Programmiersprache C Zeiger und Felder. Andreas Polze 1

Arrays. Theorieteil. Inhaltsverzeichnis. Begriffe. Programmieren mit Java Modul 3. 1 Modulübersicht 3

Dynamische Datentypen. Destruktor, Copy-Konstruktor, Zuweisungsoperator, Dynamischer Datentyp, Vektoren

Felder (Arrays) und Zeiger (Pointers) - Teil I

Zusammenfassung des Handzettels für Programmieren in C

Felder (Arrays) und Zeiger (Pointers) - Teil I

7. Übung Informatik II - Objektorientierte Programmierung

3.8 Objekttypen und Arrays. Wir werden uns in diesem Kapitel näher mit den Objekttypen in Java beschäftigen.

Einstieg in die Informatik mit Java

Verschlüsseln eines Bildes. Visuelle Kryptographie. Verschlüsseln eines Bildes. Verschlüsseln eines Bildes

Arrays (Felder/Vektoren)

C-Pointer (Zeiger, Adressen) vs. C++ Referenzen

Transkript:

1 Zeiger in Java und C/C++ Zeigervariable (kurz: Zeiger, engl.: pointer): eine Variable, die als Wert eine Speicheradresse enthält Java: Zeiger werden implizit für Referenztypen (Klassen und Arrays) verwendet, es gibt keine besondere Syntax für Zeigeroperationen C/C++: Zeiger sind eine eigene Gruppe von Datentypen und werden explizit durch den Programmierer als Zeiger deklariert 2

Motivation Warum benötigt man überhaupt Zeiger? Hauptgrund: dynamische Speicherverwaltung Adressen von Variablen werden vom Compiler festgelegt, d.h. der benötigte Speicherplatz muß zur Compilierzeit bekannt sein Problem: die genauen Daten, die das Programm verarbeiten soll, sind zur Compilierzeit i.a. nicht bekannt, der Compiler kann nicht wissen, wieviel Speicherplatz benötigt wird Lösung: Speicherplatz kann vom Programm zur Laufzeit angefordert (allokiert) werden, Zugriff auf diesen Speicherplatz erfordert Zeiger 3 Zeigerdeklaration Zeiger sind in C/C++ typisiert, d.h. eine Zeigervariable enthält Informationen darüber, auf welchen Typ sie zeigt. Zeigertypen werden bei der Deklaration durch das Zeichen "*" hinter dem Typ gekennzeichnet. Deklaration einer Variable vom Typ int (kein Zeiger): int i; Deklaration eines Zeigers auf einen Wert vom Typ int: int* j; oft auch: int *j; 4

Adressermittlung Wie kann die Adresse, die ein Zeiger speichern soll, ermittelt werden? erste Möglichkeit: Zeiger als Ergebnis einer Speicherallokation die Speicherverwaltung liefert eine Adresse auf einen Speicherbereich, den das Programm benutzen darf in C: Funktion void* malloc(size_t size) (deklariert in stdlib.h) versucht, size Bytes Speicher zu allokieren 5 Adressermittlung Ergebnis von malloc ist ein Zeiger vom Typ void* (untypisierter Zeiger), der mit allen Zeigertypen zuweisungskompatibel ist. Achtung: Der Aufruf von malloc kann fehlschlagen, Ergebnis ist dann ein Zeiger mit dem Wert 0 (Nullpointer, zur Unterscheidung von der Zahl 0 oft durch die Konstante NULL bezeichnet). Speicher für eine int-variable allokieren: int *j=malloc(sizeof(int)); 6

Adressermittlung in C++: Verwendung von malloc ist auch möglich, aber Zeiger vom Typ void* erfordern explizite Typumwandlung (type cast, Syntax wie in Java) int *j=(int *)malloc(sizeof(int)); Besser in C++: Verwendung des new-operators, da bei Klassen automatisch Konstruktoren aufgerufen werden int *j=new int; 7 Adressermittlung Zweite Möglichkeit: Zeiger auf Adresse einer bereits existierenden Variablen in C und C++: der unäre Operator & liefert die Adresse der hinter ihm stehenden Variablen (nicht zu verwechseln mit dem binären Operator &, der das bitweise logische Und bildet) int i; int *j=&i; j enthält die Adresse von i 8

Speicherfreigabe C/C++: Die Funktion free(void *ptr) (ebenfalls in stdlib.h deklariert) gibt einen mit malloc allokierten Speicherbereich frei. free(j); C++: Der Operator delete ruft bei Klassen den Destruktor auf und gibt den mit new allokierten Speicherbereich frei. delete j; Niemals mit malloc allokierten Speicher mit delete oder mit new allokierten Speicher mit free freigeben! 9 Dereferenzierung von Zeigern Dereferenzierung: Zugriff auf den Wert, der an der in der Zeigervariablen gespeicherten Adresse steht ("der Wert, auf den der Zeiger zeigt") Zur Dereferenzierung eines Zeigers dient der unäre Operator * (nicht zu verwechseln mit dem binären Multiplikationsoperator *). Beispiel: int *i=new int; int j; *i=3; j=*i;//j hat nach dieser Zeile den Wert 3 10

Pointer Aliasing Pointer Aliasing: Zwei Zeiger enthalten dieselbe Adresse oder ein Zeiger enthält die Adresse einer anderen sichtbaren Variablen. Der eine Zeiger ist dann ein Alias des anderen Zeigers bzw. der Variablen. Unnötiges Pointer Aliasing sollte vermieden werden, da es dem Compiler die Optimierung erschwert. Beispiel: int i=1; int *j=&i; *j=3;//i wird über Alias j geändert Optimierungsproblem: i kann nicht in einem CPU-Register gehalten werden, da der Wert im Speicher geändert wird. 11 Arrays Array in C und C++: Zusammenhängender Speicherbereich einer festen (zur Compilierzeit bekannten) Größe Die Arrayvariable wird wie ein Zeiger auf den Anfang dieses Speicherbereichs behandelt. Deklaration eines Arrays: Typ Name[Anzahl der Elemente] Beispiel: Array mit 100 Elementen vom Typ int: int i[100]; Zugriff auf Arrayelemente: wie in Java i[12]++; //Element mit Index 12 erhöhen Es gibt kein Feld length bei Arrays in C/C++. 12

Arrays Vorsicht beim Zugriff auf Arrayelemente: Es findet keine Bereichsüberprüfung statt. Ändern eines Arrayelements mit einem Index außerhalb der Arraygröße führt zum Überschreiben von fremdem Speicher (kann eigenes Programm oder unter manchen Betriebssystemen auch andere Programme ungewollt verändern). (das ist gültiger C-Code!) int data[10]; int index=-10000; data[index]=0; //BOOM! 13 Pufferüberlauf - Buffer Overflow Häufiger Fehler in C/C++-Programmen: die fehlende Bereichsüberprüfung wird nicht berücksichtigt, wenn externe Daten eingelesen werden, der Lesepuffer kann überlaufen (Buffer Overflow) besonders konstruierte Eingabedaten können das Programm gezielt verändern besonders gefährdet sind Programme, die Eingaben aus dem Internet verarbeiten (z.b. HTTP-Server) Angreifer können den Fehler ausnutzen, um beliebigen Programmcode auf dem Zielrechner auszuführen (sog. Internet-Würmer führen solche Attacken automatisiert durch (Bsp: Code Red)) 14

Pufferüberlauf - Buffer Overflow Beispiel für ein Programm mit einem Buffer Overflow- Fehler (kopiert zeilenweise Eingabe nach Ausgabe): #include <stdio.h> void main() { char buf[1000]; //no line is longer while(gets(buf)!=null) //read line { puts(buf); //write line } } 15 Pufferüberlauf - Buffer Overflow Wie kann ein Angreifer beliebigen Programmcode ausführen? Stack nach dem Aufrufen der main-funktion: buf[0] buf[1] buf[999] Rücksprungadresse niedrige Adressen (Der Stack wächst auf x86- Systemen in Richtung niedrige Adressen.) hohe Adressen 16

Pufferüberlauf - Buffer Overflow Der Angreifer erzeugt eine Textzeile, die länger als 1000 Zeichen ist. Dadurch wird die Rücksprungadresse überschrieben und das Programm stürzt beim Verlassen der main- Funktion ab (im günstigsten Fall). Die Kunst des Angreifers besteht darin, die Rücksprungadresse so zu überschreiben, das der neue Wert in den Puffer zeigt. Dort kann beliebiger Programmcode stehen (der vorher als Textzeile eingelesen wurde). Deshalb: Niemals irgendwelche Annahmen über fremde Eingabedaten machen, ohne sie nachzuprüfen! 17 Pufferüberlauf - Buffer Overflow Beispiel für einen speziell konstruierten HTTP-Request-String (aus dem Logfile eines Webservers, erzeugt vom Wurm Code Red II, infizierte weltweit ca. 400000 MS Internet Information Server innerhalb weniger Stunden): GET /default.ida?xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX%u9090% u6858%ucbd3%u7801%u9090%u6858%ucbd3%u7801%u9090% u6858%ucbd3%u7801%u9090%u9090%u8190%u00c3%u0003% u8b00%u531b%u53ff%u0078%u0000%u00=a nur zum Füllen des Puffers eingeschleuster Code 18

Strings Strings werden in C durch char-arrays dargestellt, das Ende des Strings wird durch ein Element mit dem Wert 0 markiert (Strings in C sind nullterminiert). Es können String-Konstanten verwendet werden (Notation wie in Java), der Compiler erzeugt dann selbst ein entsprechendes char-array. Beispiel: char *s1="text"; char s2[5]; s2[0]='t'; s2[1]='e'; s2[2]='x'; s2[3]='t'; s2[4]=0; s1 und s2 zeigen beide auf einen String "Text" 19 Zeigerarithmetik In Java: Referenzen (Zeiger) sind fest und können nur durch Zuweisen einer anderen Referenz verändert werden. In C/C++: Zu Zeigern können Werte addiert und subtrahiert werden (Zeigerarithmetik), dadurch ist z.b. das schrittweise Schieben eines Zeigers über ein Array möglich. Addieren eines Wertes zu einem Zeiger erhöht den Zeiger um diesen Wert multipliziert mit der Größe des Typs, auf den der Zeiger zeigt. (Subtraktion funktioniert analog) Mit Zeigern vom Typ void* ist keine Zeigerarithmetik möglich (void hat keine Größe). 20

Zeigerarithmetik Beispiel: Füllen eines Arrays mit 0 Ohne Zeigerarithmetik: #define size 100; int data[size]; int i; for(i=0;i!=size;i++) data[i]=0; Mit Zeigerarithmetik: #define size 100; int data[size]; int *i; for(i=data;i!=(data+size);i++) *i=0; 21 Referenzen in C++ Nur in C++: Referenzen sind ein weiterer Zeigertyp, der nur für Funktionsparameter verwendet werden kann. Referenzen sind Zeiger, werden aber automatisch dereferenziert (ähnlich wie in Java) und die Adresse kann nicht verändert werden. Deklaration einer Referenz: wie Zeiger, aber & statt * Beispiel: void setinttoone(int &i) { i=1; } 22

Referenzen in C++ Dasselbe Beispiel mit normalen Zeigern statt Referenzen: void setinttoone(int *i) { *i=1; } Nach Möglichkeit sollte man Referenzen den Zeigern vorziehen, da der Compiler sie besser optimieren kann (kein Aliasing möglich). 23 Zusammenfassung Zeiger sind ein mächtiges Werkzeug in C und C++ und werden oft benötigt, aber: Fehlerhafter Umgang mit Zeigern ist die wahrscheinlich häufigste Ursache für Fehler in C/C++-Programmen. Oft vorkommende Fehler sind: Dereferenzierung von Zeigern, nachdem ihr Speicherbereich freigegeben (oder noch schlimmer: schon wieder anderweitig vergeben) wurde ("wilde Zeiger") Überschreitung von Arraygrenzen (Buffer Overflow) Sorgfältiges Arbeiten mit Zeigern ist notwendig. 24