PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Speicherzugriffsfehler



BloodyBullet
11-09-2004, 12:16
Hallo,

bin noch ziehmlich neu in der Materie, deshalb habe ich eine wahrscheinlich banale, für mich dennoch schwierige Frage, wobei ihr mir vielleicht helfen könnt.

Folgender Code wird erfolgreich übersetzt und ausgeführt, sobald ich aber mehr als fünf Buchstaben eingebe, wird ein Speicherzugriffsfehler gemeldet.

{
char v;
char n;
char p;
printf("Vorname: ");
scanf("%s", &v);
printf("Nachname: ");
scanf("%s", &n);
printf("Code: ");
scanf("%s", &p);
}
Ich gehe mal davon aus, dass der reservierte Speicherplatz für die Variablen überstiegen wird. Nur wie kann ich denen dann mehr zuweisen?

MfG

locus vivendi
11-09-2004, 13:28
Das ist in der Tat eine einfache Angelegenheit. Deine Vermutung ist auch schon richtig, in der Tat übersteigt der Speicherplatz für fünf Buchstaben die der char Variable in die geschrieben wird. Mehr speicher kannst du z.B. durch malloc anfordern, oder dadurch das du die Address eines Arrays übergibts. Das Problem mit einem Solchen Ansatz ist, das der Speicher dann immer noch überlaufen kann, und auch meistens wird. Beispiel: Du reservierst Speicher für 20 Buchstaben weil du keinen Nahmen kennst der länger als 20 Buchstaben ist. Aber was ist wenn doch mal jemand kommt der einen längeren Namen hat? Dein Programm stürzt vermutlich wieder ab. Du hast, um auf der sicheren Seite zu sein also zwei Alternativen: Entweder du schneidest das Lesen nach einer bestimmten Anzahl von Zeichen ab. Das löst dein Problem aber nicht wirklich. Dann wird der Mensch mit einem längeren Namen zwar nicht dein Programm zu Absturz bringen, aber er kann seine Namen trotzdem nicht richtig eingeben. Oder du benutzt eine Eingaberoutine die immer wenn Speicherbereich voll wird, den Speicher vergrößert. Damit hast du das Problem gelöst.

Nun hast du nicht gesagt ob du mit C oder C++ arbeitest. Dein Snippet könnte beides sein. Deshalb sage ich dir einfach mal wie man das mit C++ machen kann:



#include <iostream> // für Eingabe/Ausgabe routinen

...

{
std::string vorname, nachname, p;

std::cout << "\nVorname";
std::cin >> vorname;
std::cout << "\nNachname";
std::cin >> nachname;
std::cout << "\ncode";
std::cin >> p;

...
}

Dieser Ausschnitt ist ziemlich robust. Insbesondere wird kein Speicherzugriffsfehler auftreten weil die C++ Eingaberoutinen für formatierte Eingabe selbstätig genügend viel Speicher anlegen.

Auch wenn du diesen Ausschnitt jetzt übernehmen könntest, würde ich dir trotzdem dazu raten, ein gutes Buch oder wenigstens gute Online-Ressourcen zum Thema (Programmieren mit C++ (oder C) ) zu lesen.

BloodyBullet
11-09-2004, 14:51
Das ist in der Tat eine einfache Angelegenheit. Deine Vermutung ist auch schon richtig, in der Tat übersteigt der Speicherplatz für fünf Buchstaben die der char Variable in die geschrieben wird. Mehr speicher kannst du z.B. durch malloc anfordern, oder dadurch das du die Address eines Arrays übergibts. Das Problem mit einem Solchen Ansatz ist, das der Speicher dann immer noch überlaufen kann, und auch meistens wird. Beispiel: Du reservierst Speicher für 20 Buchstaben weil du keinen Nahmen kennst der länger als 20 Buchstaben ist. Aber was ist wenn doch mal jemand kommt der einen längeren Namen hat? Dein Programm stürzt vermutlich wieder ab. Du hast, um auf der sicheren Seite zu sein also zwei Alternativen: Entweder du schneidest das Lesen nach einer bestimmten Anzahl von Zeichen ab. Das löst dein Problem aber nicht wirklich. Dann wird der Mensch mit einem längeren Namen zwar nicht dein Programm zu Absturz bringen, aber er kann seine Namen trotzdem nicht richtig eingeben. Oder du benutzt eine Eingaberoutine die immer wenn Speicherbereich voll wird, den Speicher vergrößert. Damit hast du das Problem gelöst.

Nun hast du nicht gesagt ob du mit C oder C++ arbeitest. Dein Snippet könnte beides sein. Deshalb sage ich dir einfach mal wie man das mit C++ machen kann:



#include <iostream> // für Eingabe/Ausgabe routinen

...

{
std::string vorname, nachname, p;

std::cout << "\nVorname";
std::cin >> vorname;
std::cout << "\nNachname";
std::cin >> nachname;
std::cout << "\ncode";
std::cin >> p;

...
}

Dieser Ausschnitt ist ziemlich robust. Insbesondere wird kein Speicherzugriffsfehler auftreten weil die C++ Eingaberoutinen für formatierte Eingabe selbstätig genügend viel Speicher anlegen.

Auch wenn du diesen Ausschnitt jetzt übernehmen könntest, würde ich dir trotzdem dazu raten, ein gutes Buch oder wenigstens gute Online-Ressourcen zum Thema (Programmieren mit C++ (oder C) ) zu lesen.
C++ ist gut, schreibe es dennoch in C.
Eine Routine zu schreiben, welche automatisch den Speicher vergrößert, wäre ja kein Problem. Nur weiß ich jetzt nicht, von welchem Typ die Variablen sein müssten, wenn die Zeichenlänge 20 Zeichen beträgt.

MfG

locus vivendi
11-09-2004, 18:29
Nur weiß ich jetzt nicht, von welchem Typ die Variablen sein müssten, wenn die Zeichenlänge 20 Zeichen beträgt.

Erstens: An scanf musst du für den Format-String "Schalter" %s einen Zeiger auf char übergeben. Das tust du in deinem Snippet auch.

Zweitens: Dieser Zeiger muss auf einen Speicherbereich zeigen, der groß genug ist, um alle gelesenen Zeichen plus eventuell ein abschließendes '\0' aufzunehmen. Im Prinzip kann das jede Variable sein. In der Praxis ist das aber meistens entweder ein Array, oder dynamisch angeforderter Speicher.
(Naja gut, das "meistens" ist eine Vermutung von mir, ich kenne keine Statistik darüber.)

Drittens: scanf und dynamische Vergrößerung des Speichers anzuwenden dürfte gar nicht so ganz einfach sein. Zeichenweise Eingabe wird vermutlich einfacher sein.

wraith
11-09-2004, 23:32
CNur weiß ich jetzt nicht, von welchem Typ die Variablen sein müssten, wenn die Zeichenlänge 20 Zeichen beträgt.



char str[21]; //Platz für 20 Zeichen + ein Zeichen für das Stringendezeichen
scanf("%20s",str);

Jetzt kannst du bis zu 20 Zeichen einlesen, und auch nicht mehr (kein Bufferoverflow möglich).

BloodyBullet
12-09-2004, 18:36
char str[21]; //Platz für 20 Zeichen + ein Zeichen für das Stringendezeichen
scanf("%20s",str);

Jetzt kannst du bis zu 20 Zeichen einlesen, und auch nicht mehr (kein Bufferoverflow möglich).
Großen Dank!

MfG