segmentation fault - für anfänger?
-
HOihoi mein Compiler, mit dem ich mein kleines Programm geschrieben hab, gibt mir bei der Fehlersuche "Zugriffsverletzung(Segmentation fault)" aus, kann mir mal jemand bitte eine für Anfänger verständliche Erklärung/Lösung zeigen, um mein programm zum laufen zu bekommen?! Hier der Quellcode:
[cpp]#include <iostream> #include <fstream> #include <string> using namespace std; int main() { int woerter=0; int zeichen=0; int saetze=0; fstream quelle; string quelldateiname; string datei; cout << "Quelldatei : "; cin >> quelldateiname; // Datei öffnen, lesen, schließen quelle.open(quelldateiname.c_str(), ios::binary|ios::in); quelle.read(reinterpret_cast<char*>(&datei), sizeof(datei)); quelle.close(); if (!quelle) cout << "Dateierror" << "\n--------------" << endl; for (int i=0; i<datei.size(); i++) { zeichen++; //vermeidet d. einlesen einer leerzeichen- Reihe while (datei[i] == datei[i++] && datei[i++] == ' ') { i++; } if (datei[i] == ' ') woerter++; //fragt die anzahl d. punkte (Sätze) in der Datei ab, vermeidet einlesen von z.B. "..." while (datei[i] == datei[i++] && datei[i++] == '.') { i++; } if (datei[i] == '.') saetze++; } cout << "Woerter : " << woerter << endl; cout << "Zeichen : " << zeichen << endl; cout << "Saetze : " << saetze << endl; system("pause"); } [/cpp]Das problem liegt laut Fehlersuche nach "quelle.open(quelldateiname.c_str(), ios::binary|ios::in);", Compiler compiliert zwar, bricht aber nach d. eingabe des Dateinamen ab (zeigt nicht mal mehr "Dateierror") und hinterlässt mir die Fehlermeldung "Unbenannt2.exe (->name d. programms) hat ein Problem festgestellt und muss beendet werden" => Was kann ich tun, um mein Programm zum laufen zu bringen?? Bitte HILFe

-
Der Fehler liegt hier (1):
quelle.read(reinterpret_cast<char*>(&datei), sizeof(datei));und
while (datei[i] == datei[i++] && datei[i++] == ' ')hier(2) und
while (datei[i] == datei[i++] && datei[i++] == '.')(3) usw.
(1) std::string ist kein POD (oder besteht nicht ausschließlich aus diesen) und kann d.h. nicht einfach so gespeichert werden! (Das Problem ist, das std::string intern mit einem Zeiger arbeitet um eine dynamische Stringlänge möglich zu machen ... ). Schreib nicht "binär" und nutze einfach den operator<< bzw. >> um Daten rein und raus zu schreiben.
(2) deine Schleife geht von i = 0 bis i < string_länge ... wenn i = string_länge - 1 und du dann i zwei mal Inkrementierst (i++), ist i = string_länge + 1 und damit greifst du in einen undefinierten Bereich, was zu undefiniertem Verhalten führt.
(3) s. (2).usw. noch ein paar Kleinigkeiten sind falsch ...
-
Vielen Dank schonmal, ich werd versuchen das so gut wie möglich umzusetzen, ein paar fragen bleiben dennoch offen:Das Problem ist, das std::string intern mit einem Zeiger arbeitet um eine dynamische Stringlänge möglich zu machen
Wie kann ich das umsetzen? würde eine char- Variable ihren Zweck erfüllen?
usw. noch ein paar Kleinigkeiten sind falsch ...
könntest du mir bitte die "Kleinigkeiten" verraten? Ich bin mir nicht sicher was du damit meinst

-
Würde die Typenumwandlung so funktionieren?:
[cpp]char datei_read; //[...] for(int j=1; j<datei_read; j++) datei[j] = datei_read;[/cpp]
-
Wie kann ich das umsetzen? würde eine char- Variable ihren Zweck erfüllen?
Naja das Problem ist nicht einen char-Array zu lesen, sondern vielmehr, dass man wissen muss, wie lang der Array ist! Deswegen musst du die länge mitspeichern ...
quelle.close(); if (!quelle) cout << "Dateierror" << "\n--------------" << endl;Hier ist eine der Kleinigkeiten. Du kontrollierst nicht ob die Datei geöffnet werden konnte, da du die Datei ja bereits geschlossen hast, sondern ob ein bad/fail-bit gesetzt ist. (D.h. wenn read fehlgeschlagen ist). Und dann solltest du, wenn schon die Datei nicht korrekt gelesen werden konnte auch mit return aus der Funktion springen und nicht einfach weiter einlesen (geht eh nicht mehr!)...
usw. noch ein paar Kleinigkeiten drin ^^
-
Habs jetzt endlich zum laufen (und funktionieren) gebracht! Sin wohl noch grobe Macken drin, hab auch fast alle for- schleifen mal mit 1 definiert, wahrscheinlich hab ichs etwas zu kompliziert gemacht, aber wenigstens erfüllt das Programm jetzt seine Funktion
. Falls jemand noch einen Tipp oder sonstiges hat, nur zu
.
Ich poste einfach mal den Code:#include <iostream> #include <fstream> #include <string> using namespace std; int main() { int woerter=0; int zeichen=0; int saetze=0; char datei_read; string datei; char zeichen_d[10000]; fstream quelle; string quelldateiname; cout << "Quelldatei : "; cin >> quelldateiname; // Datei öffnen, lesen, schließen quelle.open(quelldateiname.c_str(), ios::in); quelle.read(reinterpret_cast<char*>(&datei_read), sizeof(datei_read)); if (!quelle) { cout << "Dateierror" << "\n--------------" << endl; return 0; } quelle.close(); //Typenumwandlung von char in string for(int j=1; j<datei_read; j++) datei_read = datei[j]; //Typenumwandlung von string nach char[] for(int h=0; h < datei.size(); h++) datei[h] = zeichen_d[h]; for (int i=1; i<9000; i++) { zeichen++; //vermeidet d. einlesen einer leerzeichen- Reihe while (zeichen_d[i] == zeichen_d[i++] && zeichen_d[i++] == ' ') { i++; } if (datei[i] == ' ') woerter++; //fragt die anzahl d. punkte (Sätze) in der Datei ab, vermeidet einlesen von z.B. "..." while (zeichen_d[i] == zeichen_d[i++] && zeichen_d[i++] == '.') { i++; } if (datei[i] == '.') saetze++; } cout << "Woerter : " << woerter << endl; cout << "Zeichen : " << zeichen << endl; cout << "Saetze : " << saetze << endl; system("pause"); }Sind die vielen Typenumwandlungen eigentlich wirklich nötig?
-
Sorry, aber dein Programm ist so auch noch voller Fehler.
Du solltest dir noch mal ein C++ Tutorial von Anfang an durcharbeiten (insb. die Datentypen, z.B. Verwendung von std::string).
-
//Typenumwandlung von char in string for(int j=1; j<datei_read; j++) datei_read = datei[j]; //Typenumwandlung von string nach char[] for(int h=0; h < datei.size(); h++) datei[h] = zeichen_d[h];was soll das bewirken?
Davon mal abgesehen, dass es abstürzen müsste, da "datei" nicht wirklich so groß ist, dass du mit i < datei_read dadrauf zugreifen kannst 
-
Ja, ihr habt wahrscheinlich recht... werd mir noch mal das ein oder andere Tutorial ansehen müssen, trotzdem danke für die Hilfe

Ach ja @(D)Evil: in die Mitte und am Ende davon wollte ich eigentlich eine Kontrolle mit cout schreiben, weil ich mir nicht sicher war, ob man das so machen kann
...
Ich weiß... hab wirklich einige tut. nötig
-
double *T schrieb:
while (zeichen_d[i] == zeichen_d[i++] && zeichen_d[i++] == ' ')Ist das nicht undefined behaviour? Zwischen zwei Sequenzpunkten darf eine Variable, die verändert wird doch nur verwendet werden, um den neuen Wert festzustellen und sonst für nichts...
http://www.angelikalanger.com/Articles/VSJ/SequencePoints/SequencePoints.html
The crux is that in the expression zeichen_d[i] == zeichen_d[i++] there are two accesses to variable i and one of the accesses, namely the i++, is a modifying access. Since the order of evaluation between sequence points is not defined we do not know whether i will be modified before it will be read or whether it will be read before the modification.
Felix :xmas1: :xmas2: