| | |
Handling exceptions
Please support our C++ advertiser: Intel Parallel Studio Home
Thread Solved |
Hey guys,
How do you handle exceptions in your programs? For instance, I have this function:
How would I handle the throw at line 7? Only with a try-catch block, or is it also possible to call the exception.what() in the terminate function?
Here's the rest of the program, I'd like to make my terminate function show what went wrong, to really have 1 central place for all the fatal errors.
How do you handle exceptions in your programs? For instance, I have this function:
cpp Syntax (Toggle Plain Text)
bool load_file(const char *filepath, std::string &dest) throw (std::bad_alloc, std::runtime_error) { using namespace std; ifstream file; file.open(filepath, ios::binary); if (!file.good()) { throw runtime_error("Couldn't open the file"); } //get filesize in bytes from ifstream //seek end, get pointer, rewind file.seekg(0, ios_base::end); size_t file_size = file.tellg(); file.seekg(0, ios_base::beg); if (!file.good()) { throw runtime_error("Fatal error while getting filesize."); } //read file in string from ifstream //allocate array, read file in array, set the term. null byte, set string to array char *file_content; try { file_content = new char [file_size+1]; } catch (bad_alloc &memException) { cerr << "Probably went out of memory while allocating " << file_size+1 << " bytes!" << endl; file.close(); throw; } file.read(file_content, file_size); file_content[file_size] = '\0'; dest = file_content; //clean up //close file, free array file.close(); delete[] file_content; return true; }
How would I handle the throw at line 7? Only with a try-catch block, or is it also possible to call the exception.what() in the terminate function?
Here's the rest of the program, I'd like to make my terminate function show what went wrong, to really have 1 central place for all the fatal errors.
cpp Syntax (Toggle Plain Text)
#include <iostream> #include <fstream> #include <string> #include <new> #include <stdexcept> /* load_file(filepath, destination) -Returns whether it succeed or not. True meaning succeeded. -Takes a path and writes to a std::string, completely memory safe. */ bool load_file(const char *filepath, std::string &dest) throw (std::bad_alloc, std::runtime_error) { --------------------cut here-------------------- return true; } void custom_terminate() { std::cerr << "--Aye, unrecoverable exception thrown!\n" << "Try doing what the messages say (if anything) and run the program again or ask someone with a bit more expertise to help you out." << std::endl; std::abort(); } int main() { using namespace std; set_terminate(custom_terminate); string file_content; load_file("test.sss", file_content); cout << file_content; return 0; }
Last edited by Clockowl; Apr 15th, 2009 at 7:57 pm.
Of course, you need try-catch construct to intercept exceptions. Nobody can call what() member function without alive (raised) exception object: what() of ... what?
What's a problem?
What's a problem?
c++ Syntax (Toggle Plain Text)
int main() { int rc = 0; // prologue try { // processing } catch (runtime_error& ups) { cerr << ups.what() << ... rc = 1; } ... other selected exception handlers catch (...) { // (total crash ;) cerr << "*** unknown exception..." ... rc = 2; } // epilogue return rc; }
I believe you do in fact catch the exception as it is "going on". And since you can catch different exception types, you can tell which is which.
Here's a simplified version of loadFile. More ... stringy. Less ... errory.
Here's a simplified version of loadFile. More ... stringy. Less ... errory.
C++ Syntax (Toggle Plain Text)
#include <iostream> #include <fstream> #include <string> #include <stdexcept> std::string loadFile ( const char* path ) throw (std::runtime_error) { std::string fileContent; std::ifstream fin ( path ); if ( !fin ) throw std::runtime_error ( "Couldn't open file" ); std::string line; while ( getline ( fin, line )) { fileContent += line; fileContent += '\n'; } return fileContent; } int main ( int argc, char** argv ) { std::string file = loadFile ( "myfile.txt" ); std::cout << file; }
Think again about exception handling pragmatics. You raise exception deep inside a function call stack when a (relatively) low level function does not know what to do in this case or it can't inform user because it has no access to user interface (console?.. windows?.. or it's a service w/o UI? ). Another example: your function detected i/o error and can't continue but this program user has very confused notions about files, databases and other computer rattles. Let my boss(es) decides what to do and how to inform my user in this case: that's exception raising logics.
On the one hand you can react to possible failures on the right level, on the other hand you can improve your code: no need in awkward "if return code is OK" cascades now. To raise an exception is a natural method to react on failures in class constructors (they can't inform about failures via return codes).
That's why I can't understand your question: There's no way of catching the exception "going on" ? I can only check whether there's one (from anywhere in the code?), but not which one? You can catch different classes of exceptions by different catch clauses:
Some remarks on your example code. The loadFile function returns boolean value. Evidently it's a classical return code: true if all done or false on failure. However the only possible return code value is true (if the function can't open file it raises an exception). That's a good example of inconsistent design. Yet another defect: in critical situation (no more memory) your function prints the message to consiole then reraises an exception. Ok, now you have a good chance to be aborted (because probably stream i/o routines want memory too) then you (probably) will get yet another "no memory" message(s) from this exception handler(s) - and you can't reuse this wonderful fucntion in GUI environment (no cerr in GUI programs)...
Apropos: the simplest way to check stream state is:
On the one hand you can react to possible failures on the right level, on the other hand you can improve your code: no need in awkward "if return code is OK" cascades now. To raise an exception is a natural method to react on failures in class constructors (they can't inform about failures via return codes).
That's why I can't understand your question: There's no way of catching the exception "going on" ? I can only check whether there's one (from anywhere in the code?), but not which one? You can catch different classes of exceptions by different catch clauses:
c++ Syntax (Toggle Plain Text)
try { ...simple and clear mainstream code } catch (can_t_open& ex) { ... } catch (can_t_close& ex) { ... } catch (we_re_done_for& ex) { ... } catch (...) // other troubles ... }
Apropos: the simplest way to check stream state is:
c++ Syntax (Toggle Plain Text)
if (!f) { // eof, bad or failed states ...
Last edited by ArkM; Apr 16th, 2009 at 2:54 am.
The true or false return was from the earlier version, was to be removed, you're right.
The second defect, I hadn't noticed. But it is a defect for sure? New doesn't allocate any memory since it can allocate the whole block right? So, new doesn't allocate blocks of half the size you wanted, just because he couldn't get it all. New allocates either zero bytes or all the requested bytes? In that case, there will be no problem I think: Program can't allocate all memory, gets none, lots of memory free, plenty for the error message.
On the other part (using cerr), I'm not sure what to do about it. Maybe I'll reroute output from cerr to another ofstream in case I want to create a program with a GUI.
Apropos: That saves typing 7 chars. I think I can handle those.
The second defect, I hadn't noticed. But it is a defect for sure? New doesn't allocate any memory since it can allocate the whole block right? So, new doesn't allocate blocks of half the size you wanted, just because he couldn't get it all. New allocates either zero bytes or all the requested bytes? In that case, there will be no problem I think: Program can't allocate all memory, gets none, lots of memory free, plenty for the error message.
On the other part (using cerr), I'm not sure what to do about it. Maybe I'll reroute output from cerr to another ofstream in case I want to create a program with a GUI.
Apropos: That saves typing 7 chars. I think I can handle those.
About the second point. I think that error message printing on too low level is a very harmful practice. In that case we have a chance to get a bucket of messages on a single failure. Besides that low level routines can't print sensible messages because they have no wide context info. For example, the only sqrt calculation routine message is "Alas, my argument is lesser than zero" - well, it can't be helped. Now you can't use this damned routine in GUI codes - std::cerr object does not exist there...
I'm not sure that exception on open file operation failed is a good idea (of course, it depends on developed system architecture). As usually we don't open files in every line of code. It's not so hard to check return code from loadFile routine (file is loaded or not loaded). Exceptions are suitable for extraordinary, as usually fatal (global) events. Yet another example of local failures where exceptions are suitable: get next token calls in syntax parsers (or get next CSV field in data importers). We can avoid annoying return code checks if getnexttoken will raise an exception if no token or bad token detected. We'll catch this exception locally, make recovery, print sensible message etc.
I'm not sure that exception on open file operation failed is a good idea (of course, it depends on developed system architecture). As usually we don't open files in every line of code. It's not so hard to check return code from loadFile routine (file is loaded or not loaded). Exceptions are suitable for extraordinary, as usually fatal (global) events. Yet another example of local failures where exceptions are suitable: get next token calls in syntax parsers (or get next CSV field in data importers). We can avoid annoying return code checks if getnexttoken will raise an exception if no token or bad token detected. We'll catch this exception locally, make recovery, print sensible message etc.
![]() |
Similar Threads
- Exception handling statement. (JavaScript / DHTML / AJAX)
- Handling Exceptions - Program ignoring specific characters for if statements (C++)
- Exception handling (Java)
- Help (Java)
- Exception Handling (C++)
- Arithmetic Exceptions and exception-handling statements (Java)
- Catching exceptions in C++ (C++)
Other Threads in the C++ Forum
- Previous Thread: parsing conf file in c++
- Next Thread: not reading from fstream
| Thread Tools | Search this Thread |
api application array arrays based beginner binary bitmap c++ c/c++ calculator char char* class classes code coding compile compiler console conversion convert count data database delete deploy developer dll download dynamiccharacterarray email encryption error file forms fstream function functions game generator getline givemetehcodez graph homeworkhelp homeworkhelper iamthwee ifstream input int java lib list loop looping loops map math matrix memory multiple news node number numbertoword output parameter pointer problem program programming project proxy python random read recursion recursive reference rpg simple sorting string strings temperature template text tree url variable vector video visual visualstudio win32 windows winsock word wordfrequency wxwidgets






It makes sense. 