Pufferüberlauf, Namespaces und andere Katastrophen

Schnelle objektorientierte, kompilierende Programmiersprache.
Benutzeravatar
Kerli
Beiträge: 1456
Registriert: So Jul 06, 2008 10:17 am
Wohnort: Österreich
Kontaktdaten:

Re: Pufferüberlauf, Namespaces und andere Katastrophen

Beitrag von Kerli » Sa Okt 31, 2009 5:45 pm

Bebu hat geschrieben:Erste Frage: Kann dieses Programm bedenkenlos jede Art von Dateien kopieren? Ich hab es mal versucht, bin mir aber über das Ergebnis nicht ganz sicher, der erster Eindruck war, dass es geht. Binärdateien bestehen ja eigentlich auch nur aus Zeichen.
Unter Linux sollte es keinen Unterschied machen, aber unter Windows zum Beispiel werden dann automatisch die Zeilenenden konvertiert. Beim Laden wird aus \r\n ein \n und beim Speicher umgekehrt. Wenn es sich also wirklich um Binärdaten handelt und eine Bitfolge zufällig \r oder \n entspricht, dann kann das durchaus unerwünschte Folgen haben.
Bebu hat geschrieben:3. Frage: Enthält die Funktion cin eine Feldgrenzenüberwachung? Wenn nicht, wie kann ich die Größe der Daten im Puffer überprüfen, bevor ich sie in eine Variable schreibe?
Die Frage ist, wozu musst du eigentlich wissen wie viele Zeichen genau im Datenstrom stehen? Bei Streams geht es ja eigentlich darum das zu abstrahieren und es somit möglich machen dass man Tastatur, Dateien und sogar auch Daten aus dem Netzwerk einheitlich zu behandeln. Und außer bei Dateien wäre es auch etwas schwierig herauszufinden wie viele Zeichen noch kommen. Deshalb liest man normalerweise auch nicht eine bestimmte Anzahl von Zeichen, sonder extrahiert verschiedenen Datentypen mit dem Extraktionsoperator (>>) zb:

Code: Alles auswählen

std::ifstream file("zahlen.txt");
int zahl;
file >> zahl;
std::cout << "Zahl ist " << zahl << std::endl;
Außerdem unterstützen die Stream Klassen das RAII Idiom. Dh. man kann direkt im Konstruktor den Dateinamen angeben, und wenn der Gültigkeitsbereich der Variable verlassen wird, egal ob geplant, durch eine Exception oder sonst irgendwas, wird die Datei automatisch wieder geschlossen.
Bebu hat geschrieben:Zweite Frage: Beim Öffnen der Dateien

Code: Alles auswählen

dat_in.open(dateiquelle.c_str(),ios_base::in);
ist mir das "ios_base" ein bisschen suspekt.[...]
Im Normalfall brauchst du diese Flags auch gar nicht verwenden, da bei einem Objekt vom Typ ifstream sowieso ios_base::in und bei ofstream ios_base::out die Standardwerte sind. Du kannst die Datei also auch so öffnen:

Code: Alles auswählen

std::ifstream dat_in(dateiquelle.c_str());
"Make it idiot-proof and someone will invent an even better idiot." (programmers wisdom)

OpenGL Tutorials und vieles mehr rund ums Programmieren: http://www.tomprogs.at

Benutzeravatar
Bebu
Beiträge: 562
Registriert: Mi Okt 21, 2009 6:19 pm
Wohnort: In der Nähe von Salzburg - Bin aber kein Österreicher!

Re: Pufferüberlauf, Namespaces und andere Katastrophen

Beitrag von Bebu » Sa Okt 31, 2009 7:20 pm

Vielen Dank für eure Antworten. Bei der dritten Frage bin ich glaube ich an dem Missverständnis schuld, die Frage bezog sich nicht auf den Code, sondern war eine allgemeine Frage. Es interessiert mich aus folgendem Grund: In meinem Buch wurde das Prinzip eines Pufferüberlaufs beschrieben. Dort hieß es, das ein Pufferüberlauf auf dem Stack wie folgt abläuft: Jede Funktion bekommt einen Stackbereich bzw. Stapel zugewiesen. Dieser Stapel bleibt bestehen, solange die Funktion ausgeführt wird also im Speicher, bis zum Erreichen der Rücksprungadresse. Wird jetzt eine Funktionsinterne Variable mit mehr Daten "gefüttert" als sie fassen kann, werden die nachfolgenden Bereiche, inklusive der Rücksprungadresse überschrieben. Wird mit dem Überlauf an dieser Stelle sinnvoller Code eingeschleust, dann wird er ausgeführt, weil ja kein Rücksprung kommt.
So, wenn ich jetzt mit

Code: Alles auswählen

cin >> x //z. B. Int Variable
einen Wert übergebe, der größer ist, als der Wertebereich von int habe ich doch einen Pufferüberlauf, oder?

Wie kann ich überprüfen, wie groß der Puffer von cin ist, bevor ich den Inhalt in eine Variable, egal welcher Art schreiben?

Also so in der Art von (Achtung Pseudocode):

Code: Alles auswählen

cin  //Benutzereingabe
if (cinpuffer > sizeof(int)) 
cout << "Überlauf" << endl;
else 
cin >> Eingabevariable
Wenn Xin das schon beantwortet hat, dann entschuldige ich mich, ich ärgere mich schon die ganze Zeit damit herum mein Ubuntu 9.10 gebacken zu kriegen. Bin etwas durch den Wind und habe grad wieder 9.04 draufgeklatscht, also vergebt mir. :roll:
Wer immer nach dem Unerreichbaren jagt, der wird irgendwann auf die Schnauze fallen!

Benutzeravatar
cloidnerux
Moderator
Beiträge: 3125
Registriert: Fr Sep 26, 2008 4:37 pm
Wohnort: Ram (Gibts wirklich)

Re: Pufferüberlauf, Namespaces und andere Katastrophen

Beitrag von cloidnerux » Sa Okt 31, 2009 7:32 pm

So, wenn ich jetzt mit

Code: Alles auswählen
cin >> x //z. B. Int Variable

einen Wert übergebe, der größer ist, als der Wertebereich von int habe ich doch einen Pufferüberlauf, oder?
Nein.
Der Operator ">>" bewirkt eigentlich das man in einer Variable alle Bits um einen Wert nach rechts schiebt, aber cin hat diesen Überladen.
Beim Überladen wird einem Operator eine neue Funktion zugewiesen.
Daraus schließt sich folgendes: Wenn man den Operator ">>" eine neue Funktion zuweist, kann man das nur für bekannte Datentypen machen, wie bei normalen Funktionen.
Bei cin wurde jetzt der Opertator ">>" sohingegen überladen, das er allen "Skalartypen"(int, floats) einen Wert zuweisen kann.
Wenn du jezt aber versuchst

Code: Alles auswählen

cin >> einObjektEinerKlasse;
anzuwenden, wirst du schon beim Compilieren einen Fehler erhalten, da es keine Überladung für die gegebene Classe hast.
So ist auch ein Pufferüberlauf für alle Skalartypen ausgeschloßen.
Redundanz macht wiederholen unnötig.
quod erat expectandum

Benutzeravatar
Bebu
Beiträge: 562
Registriert: Mi Okt 21, 2009 6:19 pm
Wohnort: In der Nähe von Salzburg - Bin aber kein Österreicher!

Re: Pufferüberlauf, Namespaces und andere Katastrophen

Beitrag von Bebu » So Nov 01, 2009 7:38 pm

OK, damit kann ich was anfangen. Also muss ich mir bei der Verwendung von cin darüber keine Sorgen machen. Da ist dann wohl das größere Problem, darauf zu achten, was da noch so alles im Puffer ist und in die nachfolgende Eingabe übernommen wird.

Wo tritt den dann hauptsächlich das Problem mit den Überläufen auf? Habe ich das Problem nur, wenn ich über einen Zeiger eine Variable beschreibe, ohne auf die Größe der Variable zu achten, oder habe ich da schon wieder was falsch verstanden?
Wer immer nach dem Unerreichbaren jagt, der wird irgendwann auf die Schnauze fallen!

Benutzeravatar
cloidnerux
Moderator
Beiträge: 3125
Registriert: Fr Sep 26, 2008 4:37 pm
Wohnort: Ram (Gibts wirklich)

Re: Pufferüberlauf, Namespaces und andere Katastrophen

Beitrag von cloidnerux » So Nov 01, 2009 8:08 pm

Wo tritt den dann hauptsächlich das Problem mit den Überläufen auf? Habe ich das Problem nur, wenn ich über einen Zeiger eine Variable beschreibe, ohne auf die Größe der Variable zu achten, oder habe ich da schon wieder was falsch verstanden?
Genau das ist ein fall eines Überlaufs.
Dabei gibt es 2 Fälle:
1.Fall:
Du hast einen Int-Pointer und speicherst über

Code: Alles auswählen

int* intPtr = &einInt;
cin >> *intPtr;
Dabei wird der Pointer als int genutzt und es gibt wenig möglichkeiten eines Überlaufs.
2.Fall:
Du castest einen Pointer:

Code: Alles auswählen

int* intPtr = voidPtr;
cin >> *intPtr;
Wenn du hier einen zu kleinen Speicherbereich nutzt, hast du dann einen Buffer-Overflow.
Redundanz macht wiederholen unnötig.
quod erat expectandum

nufan
Wiki-Moderator
Beiträge: 2558
Registriert: Sa Jul 05, 2008 3:21 pm

Re: Pufferüberlauf, Namespaces und andere Katastrophen

Beitrag von nufan » So Nov 01, 2009 8:22 pm

Bufferoverflows sind auch im OpenBook "C von A bis Z" schön beschrieben:
http://openbook.galileocomputing.de/c_v ... 492bc5af73

Antworten