ios_base::failure Ausnahme nach deaktivierung der Ausnahmen für den Stream
-
Hallo Leuts.
Ich tritt folgende Ausnahme auf:
terminate called after throwing an instance of 'std::ios_base::failure'
what(): basic_ios::clearJedoch dachte ich, ich hätte die Ausnahmen deaktiviert mit
void parser_base::run(){ std::istream::iostate iostate = is.exceptions(); is.exceptions(std::istream::goodbit); first(); is.exceptions(iostate); }Ist hier was falsch?
Aufgerufen wird das ganze hier:
int main(int argc, char **argv){ if(1 < argc && argc < 3){ std::ifstream ifs; ifs.exceptions(std::ifstream::failbit | std::ifstream::badbit); try{ ifs.open(argv[1]); }catch(std::ifstream::failure &e){ std::cerr << "Couldn't open source file " << argv[1] << std::endl; exit(EXIT_FAILURE); } fifth_interpreter interpreter(ifs); //try{ interpreter.run(); ifs.close(); //}catch(std::exception &e){ // std::cerr << "Parsing error" << std::endl; //} }else std::cerr << "Wrong number of arguments" << std::endl; return EXIT_SUCCESS; }Danke,
Martin
-
Dieser Thread wurde von Moderator/in SeppJ aus dem Forum C (C89 und C99) in das Forum C++ (auch C++0x) verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
Und deine Exception wird auch sicher in first(); geworfen?
Ansonsten: Zeig mal ein vollständigeres Beispiel. Ich sehe jede Menge Code in dem Exceptions muter mal aktiviert und mal deaktiviert werden, ohne klaren Programmverlauf. Ich bin mir gar nicht sicher, an welcher Stelle du dein Problem hast und über welchen Pfad du dort hingekommen bist. Du selbst vermutlich auch nicht, sonst wäre das Problem ja nicht da
.
-
Hier die Konstruktoren die for run aufgerufen werden. Die exceptions werden nicht wieder aktiviert. Ansonsten gibt's keine weiteren Aufrufe dazwischen.
fifth_interpreter::fifth_interpreter(std::istream &is) : parser_base(is), stack(64) {} parser_base::parser_base(std::istream &is) : is(is), row(0), col(0) { next_token(); }Und hier noch next_token(), welches die Ausnahme wirft:
void parser_base::next_token(){ token = is.get(); check_token('\n') ? row++, col = 0 : col++; } [code] Diese funktion wird mehrmals innerhalb first aufgerufen. Wenn ich run() in einen try catch block stelle. Wird die Ausnahme auch aufgefangen. Erstaunlicherweiße gib't e.what() nichts zurück. [code] int main(int argc, char **argv){ if(1 < argc && argc < 3){ std::ifstream ifs; ifs.exceptions(std::ifstream::failbit | std::ifstream::badbit); try{ ifs.open(argv[1]); }catch(std::ifstream::failure &e){ std::cerr << "Couldn't open source file " << argv[1] << std::endl; exit(EXIT_FAILURE); } fifth_interpreter interpreter(ifs); try{ interpreter.run(); }catch(std::exception &e){ e.what(); std::cerr << "Parsing error" << std::endl; } ifs.close(); }else std::cerr << "Wrong number of arguments" << std::endl; return EXIT_SUCCESS; }Die einzige Ausgabe die ich erhalte is dann "Parsing error", obwohl er vorher folgendes behauptet hat:
what(): basic_ios::clear

Hier nochmal beide Klassen:
class parser_base{
public:
parser_base(std::istream &is);
void run();protected:
virtual void first() = 0;
int get_token();
unsigned int get_row();
unsigned int get_col();
void next_token();
bool check_token(int token);
void expect_token(int token);
bool check_tokens(const std::vector<int> &tokens);
void expect_tokens(const std::vector<int> &tokens);
void expect_serie(const std::vector<int> &tokens);
bool check_range(int first, int last);
void expect_range(int first, int last);
void error();
private:
std::istream &is;
int token;
unsigned int row, col;
};class fifth_interpreter : public parser_base{
public:
fifth_interpreter(std::istream &is);private:
void add_numbers(void);
void substract_numbers(void);
void multiply_numbers(void);
void divide_numbers(void);
void print_number(void);bool is_digit();
int digit();
bool is_whitespace();
void whitespace();
bool is_word_end();
void word_end();
bool is_number();
void number();
bool is_plus();
void plus();
bool is_minus();
void minus();
bool is_multiply();
void multiply();
bool is_divide();
void divide();
bool is_print();
void print();
bool is_word();
void word();
void first();fifth::stack stack;
};[/code]
-
Oh. Entschuldigung wegen der schlechten Formatierung. Da ist was mit meinen code tags shiefgelaufen. Hoffe, man kann es trotzdem erkennen.
-
Es ist für einen Helfer eher uninteressant, wie deine 100 Memberfunktionen alle heißen. Versuch doch mal nach und nach, alles unnötige aus deinem Code rauszuwerfen, bis nur noch ein Programm von 50, eventuell 100 Zeilen übrig ist, welches von den Lesern so ohne jegliche Änderungen oder Ergänzungen compiliert werden kann und an dem man den Fehler trotzdem noch sehen kann.
Wenn du während des Erstellens dieses Minimalsbeispiels auf einmal den Fehler nicht mehr bekommst, dann hast du höchstwahrscheinlich die Fehlerstelle rausgenommen und solltest dir mal genauer ansehen, was du zuletzt entfernt hast.
-
Hier noch einmal ne Zusammenfassung: Ich greife jetzt direkt auf next_token zu.
die function access_to_private_method is notwendig, da next_token private ist.fifth_interpreter::fifth_interpreter(std::istream &is) : parser_base(is), stack(64) {} parser_base::parser_base(std::istream &is) : is(is), row(0), col(0) {} void parser_base::next_token(){ token = is.get(); check_token('\n') ? row++, col = 0 : col++; } void access_to_private_method(fifth_interpreter &interpreter){ interpreter.next_token(); } int main(int argc, char **argv){ if(1 < argc && argc < 3){ std::ifstream ifs; ifs.exceptions(std::ifstream::failbit | std::ifstream::badbit); try{ ifs.open(argv[1]); }catch(std::ifstream::failure &e){ std::cerr << "Couldn't open source file " << argv[1] << std::endl; exit(EXIT_FAILURE); } fifth_interpreter interpreter(ifs); try{ std::istream::iostate iostate = ifs.exceptions(); ifs.exceptions(std::istream::goodbit); access_to_private_method(interpreter); ifs.exceptions(iostate); }catch(std::exception &e){ e.what(); std::cerr << "Parsing error" << std::endl; } ifs.close(); }else std::cerr << "Wrong number of arguments" << std::endl; return EXIT_SUCCESS; }Die eingelesene Quelldatei ist jetzt vollständig leer. Er trifft also beim Aufruf von next token sofort auf das ende des streams. Ich gehe davon aus, dass is.get() EOF zurück gibt. Oder liege ich damit falsch? Es wird jedoch sofort eine Ausmahme ohne Fehlermeldung in what() geworfen.
Eigentlich ist es ja nicht notwendig die Ausnahmen vorher zu aktivieren und dann wieder zu deaktivieren. Ich will jedoch erreichen, dass mein Interpreter auch mit aktivieren Ausnahmen funktioniert.
Hoffe das ist jetzt besser.
-
Das würde ich zwar nicht unter "compilierbares Beispiel" laufen lassen, aber mir ist trotzdem klar was passiert:
Wenn du mitifs.exceptions(iostate);die Ausnahmebehandlung wieder aktivierst, dann ist der Stream noch immer in einem Fehlerzustand und schmeißt daher prompt etwas.
-
Danke
-
Bleibt eigenlich nur noch die Fragbe offen, wieso er das lesen von EOF als Ausnahme behandelt.
Ich habe doch std::ifstream::eofbit gar nicht gesetzt. Was kann man dagegen tun? EOF soll wie ein ganz normales Zeichen behandelt werden. Es ist ein zulässiges Zeichen im Quellcode und zeigt das Ende eines Tokens an, genau wie ' ', '\n' und '\t'.
-
Martinn Kalbfuß schrieb:
EOF soll wie ein ganz normales Zeichen behandelt werden. Es ist ein zulässiges Zeichen im Quellcode und zeigt das Ende eines Tokens an, genau wie ' ', '\n' und '\t'.
Technisch gesehen ist das Dateiende kein normales Zeichen, sondern ein Zustand des Streams - an der Stelle ist jeder weitere Leseversuch sinnlos.