Zeiger Mit Länge Als Cee Idiom
StartSeite | Neues | TestSeite | ForumSeite | Teilnehmer | Kategorien | Index | Hilfe | Einstellungen | Ändern
Viele C-Funktionen bekommen lediglich den Zeiger auf einen Bufferbereich (String) als Parameter und füllen den Bufferbereich (String) ohne einen möglichen Überlauf zu kontrollieren oder kontrollieren zu können. Dieses Problem kann durch das ZeigerMitLängeAlsCeeIdiom gemildert werden.
Das ZeigerAufAusreichendPlatzAlsCeeIdiom:
| char buffer[10];
char hello[]="Hallo DseWiki!";
strcpy(buffer,hello); |
|
|
das den Programmierer - wie in diesem Beispiel - beissen kann.
Beispiele:
- relativ unproblematisch: strcpy, ...
- eher problematisch: gets, sprintf, ...
Ich möchte das hier diskutieren, deshalb nicht ändern. Zunächst scheint mir die Unterscheidung in
relativ unproblematisch und eher problematisch ungeeignet zu sein. Und es sollte eigentlich bekannt sein,
daß Buffer in C die größten Sicherheitslücken öfnen. Daher schlage ich vor das hier anders zu formulieren.
Jedes Beschreiben eines buffers ohne Längenangeben ist problematisch, und gets, sprintf zu benutzen ist einfach tödlich.
Sicherer scheint es, Funktionen zu verwenden, die dem ZeigerMitLängeAlsCeeIdiom folgen:
| char buffer[256];
fgets(buffer,sizeof(buffer),fp); |
|
|
In obigem Fall ist dies fast unausweichlich, weil sich Zeilenlängen in Textfiles nicht sinnvoll unter Kontrolle halten lassen.
Vorteile des ZeigerMitLängeAlsCeeIdiom:
- in vielen Fällen ist das Idiom ohnehin notwendig
- es bietet mehr Sicherheit gegen Fehlersituationen
- ...
Nachteile des ZeigerMitLängeAlsCeeIdiom:
- es kostet Performance und Speicherplatz
- kann auch keine Strings beliebiger Länge verarbeiten
- ...
Nach langer Zeit ein Diskussionsbeitrag | |
Obiges ist eingegeben bzw. letztgeändert in 2004, offensichtlich scheint sich niemand für dieses Thema zu interessieren. Mich hat es in den letzten Jahren durchaus immer wieder getroffen, sei es wegen Fehlersuche, aha, Bufferüberlauf, oder bei grundsätzlicher Überlegung, eine sichere Software zu schreiben. Ich habe bis vor ca. 2 Jahren beruflich hauptsächlich C schreiben müssen (embedded Systems) und C++ gewollt (am PC ausgetobt), jetzt ist es irgendwie umgekehrt. Außerdem bevorzuge ich Java.
Ich meine,
- sprintf &co sind sehr vorsichtig zu verwenden, aber sie sind nunmal in C üblich. scanf habe ich immer schon abgelehnt und nie genutzt.
- grundsätzlich sollte man wo möglich die Länge angeben!!!
Ich habe in C++ wegen datenaustausch für "Plain Old Data" geworben, das sind struct-Definitionen wie in C, und dort für Felder eine Basisstruktur Object_Array_Base_c geschaffen. Diese enthält die Länge eines feldelementes, die Anzahl der Feldelemente, eine Typkennzeichnung, und darauf folgend entweder das Feld selbst (Vorzugsvariante) oder ein Zeiger auf das Feld. Ich führe das demnächst mal genauer aus, habe jetzt nicht so viel Zeit. Etwa so
typedef struct MyArray
{ Object_Array_Base_c head;
Elementtype data[100];
}
Um dynamisch anzulegen: Die 100 müssen nicht ernst sein, nur als Debughilfe (Debugger in Visual Studio 6.0 & co zeigt die ersten 100 Elemente an). Um den richtigen Speicherplatz zu reservieren, gibt es noch ein paar passende Makros sizeof_Type usw. Die Anzahl der Elemente steht ja im head. Puritanisch sähe die richtige Definition so aus:
typedef struct MyArray
{ Object_Array_Base_c head;
Elementtype data[1];
}
weil garantiert (sollte sein) mindestens nur 1 Element da ist, aber dann sieht man nichts mehr im Debugger. Wenn man in der obigen Form zum Bsp nur 12 Elemente reserviert, findet man ab data[12] falsche Daten, aber der direkte Zugriff ohne Indexprüfung wäre zur laufzeit auch mit data* nicht gesichert und beim Debuggen sollte man wissen, was man anschaut. Das zu diesem Nebenthema.
Mit diesem Prinzip kann mit nur einem Zeiger auf diese Struktur ein verarbeitendes Programm alle Informationen lesen. Das Prinzip ist etwas aus Java abgeguckt, dort wird definiert
Typ[] array = new Typ[gewuenschte_groesse];
und die Größe ist über array.length jederzeit abfragbar. (Außerdem wird sie zur Laufzeit getestet). das Object_Array_Base ist sozusagen die Basis aller Array-Objekte.
das war ein beitrag in Kürze, mfG HartmutSchorrig
KategorieC KategorieCee
StartSeite | Neues | TestSeite | ForumSeite | Teilnehmer | Kategorien | Index | Hilfe | Einstellungen | Ändern
Text dieser Seite ändern (zuletzt geändert: 29. November 2007 8:49 (diff))