Frage zu scanf und malloc
-
Hi Leute, probiere gerade etwas mit scanf rum.
Nun habe ich mir folgende Frage gestellt: Angenommen, ich bastel so eine Konstruktion in meinen Code...char* a;
a=(char*) malloc(3 * sizeof(char));
scanf("%s",a);
printf("%s\n",a);Nun gebe ich einfach ein Wort ein, das mehr als 3 Buchstaben hat. Ich habe erwartet, dass ein Fehler auftritt, tut es aber nicht. Das Wort wird nachher auch mit printf wieder korrekt ausgegeben.
Also, was passiert da?
Ich habe ja nur 3 Speicherslots (mit char-Größe). Wird dann während der Laufzeit des Programms neuer (entsprechend großer) Speicher reserviert oder werden die nächsten freien Speicherzellen (nach den 3 reservierten) einfach überschrieben, ungeachtet dessen, ob sie frei sind oder nicht?
Oder ist etwas ganz Anderes der Fall?
Danke für die Antworten,
plizzz
-
plizzz schrieb:
Also, was passiert da?
naja, scanf schreibt gnadenlos weiter. wenn du mehr als 2 zeichen eingibst (bei malloc(3)), zerbrutzelt's dir den heap, d.h. irgendein späteres malloc oder free führt zum absturz oder funktioniert einfach nicht.
übrigens: den rückgabewert von malloc sollteste nicht casten und 'sizeof(char)' ist immer 1, kannste also weglassen.
-
hier bist du gefordert dafür zu sorgen, das die arraygrenze eingehalten wird.
-
forder0r schrieb:
hier bist du gefordert dafür zu sorgen, das die arraygrenze eingehalten wird.
Jepp, z.B. so:
void cb() // clear buffer :) { setvbuf ( stdin, NULL, _IONBF, 0 ); setvbuf ( stdin, NULL, _IONBF, BUFSIZ ); } int main() { char* a = NULL; char format0r [256] = {0}; int n = 3; a = malloc ( n ); if(!a) return 0; sprintf ( format0r, "%%%ds", n-1 ); printf ( "eingabe version 1: " ); scanf ( format0r, a ); printf( "%s\n", a ); // Eingabepuffer löschen, sonst landet der überschuessige Schrott aus der // ersten Eingabe in der zweiten, falls mehr als n-1 Zeichen eingegeben wurden! cb(); printf( "eingabe version 2: " ); // fgets sorgt dafür, das maximal n-1 Zeichen kopiert werden. fgets ( a, n, stdin ); printf( "%s\n", a ); ...
Gruß,
b.
-
Also könnte es wirklich passieren, dass ich mir durch sowas irgendeine Stelle im Speicher überschreibe, die für etwas anderes gebraucht wird?
Und wieso sollte ich den Rückgabewert nicht casten? Wenn ich nicht caste, funktioniert es nicht.
Und danke für den Lösungsansatz, werde ihn mir anschauen.
-
plizzz schrieb:
Also könnte es wirklich passieren, dass ich mir durch sowas irgendeine Stelle im Speicher überschreibe, die für etwas anderes gebraucht wird?
Und wieso sollte ich den Rückgabewert nicht casten? Wenn ich nicht caste, funktioniert es nicht.
Und danke für den Lösungsansatz, werde ihn mir anschauen.
Jepp, kann nen Pufferüberlauf geben:
http://de.wikipedia.org/wiki/Pufferüberlauf
Wenn du unter C kompilierst, dann brauchst du nicht zu casten, weil es C nun einmal nicht erfordert.
Vermutlich kompilierst du mit dem C++ switch, der wird bei einigen Compilern automatisch aktiviert, wenn die Dateien eine *.cc der *.cpp Endung haben. Machmal ne *.c Endung draus oder guck in deine Compiler -Doku ....
-
Ah ok, das stimmt. Wenn ich den Dateinamen auf *.c ändere, geht es auch ohne den Cast.
Kann ich mir durch sowas auch Speicher überschreiben, den zB grade das Betriebssystem nutzt und somit den Computer komplett zum Absturz bringen? Oder hat das Betriebssystem Speicherregionen für sich, wo ich so einfach gar nicht drauf schreiben kann?
-
das kann nicht passieren, da jedes programm einen eigenen Adressraum hat.
-
plizzz schrieb:
Kann ich mir durch sowas auch Speicher überschreiben, den zB grade das Betriebssystem nutzt und somit den Computer komplett zum Absturz bringen? Oder hat das Betriebssystem Speicherregionen für sich, wo ich so einfach gar nicht drauf schreiben kann?
wenn dein code als 'normales programm' im user-mode läuft, kann er mit falschen schreibzugriffen andere prozesse und den kernel nicht korrumpieren. das gilt jedenfalls für windows.
-
player4245 schrieb:
das kann nicht passieren, da jedes programm einen eigenen Adressraum hat.
keine pauschalisierungen bitte.
-
dann formuliere es aus, damit hilfst du dem threadersteller
-
player4245 schrieb:
dann formuliere es aus, damit hilfst du dem threadersteller
häh