ok so for most of my error handling i throw and exception and log the info of the error to a file...my question is...what should i do if the program/system is unable to log it to a file? should i throw an uncatched exception? should i just call exit()? i want to find a way that will help debugging so i can find why the log function and possibly trace back and find what error occured before that! -thx

Recommended Answers

All 4 Replies

What about showing a messagebox with the error in the exception? That way, even though you handle it, you can know what it is

There's no better way other than what Nichito mentioned.Also try to make use of the GetLastError() along with the FormatMessage() functions.These will give you a lot of info on your problems.

I don't know what made Nichito and caut_baia assume that you are using the win32 API, so let me give a more platform agnostic solution.

It is pretty simple really. First of all, your logger should give a no-throw guarantee for almost everything it does. This could be a hard requirement to fulfil depending on the complexity of your logger, which should be a simple as possible (and you might have to use low-level C-style programming to control that).

In your implementation of the logger, you should no let any exception escape and you should verify any error codes you might get (if you are using API functions that rely on error-codes like win32). If you do get errors, you should just deal with them in the logger by reverting to a less convenient but more likely to succeed mechanism for reporting the error (that could include a MessageBox or std::cerr, or even exit()). You can also try more than one (go from the most desirable/convenient to the worst (i.e. exit())).

So, your logger could do something like this:

class Logger {
  private:
    //fall-back error report:
    void log_cerr(const std::string& aMessage) throw() {
      bool succeeded = false;
      try {
        if(std::cerr << "ERROR: Logger Failure! Fall-back report: " << aMessage << std::endl)
          succeeded = true;
      } catch(...) { }; //catch-anything, do nothing ("succeeded" remains false)
      if(!succeeded)
        exit(); //last resort!
    };
  
    std::ofstream outFile;
  public:
    Logger() throw() : outFile("error.log") {
      using namespace std;
      outFile.exceptions(ofstream::eofbit | ofstream::failbit | ofstream::badbit); 
    }; 
    
    void log(const std::string& aMessage) throw() {
      try {
        outFile << aMessage << std::endl; //or something like that.
      } catch(...) { //catch-anything clause
        //revert to std::cerr:
        log_cerr(aMessage);
      };
    };
};

The "throw()" statements in the above functions are important, it signals the no-throw guarantee.

Actually, instead of exit() in mike_2000_17's code as "last resort", use ::abort() - that will generate a core dump and if your program was compiled with the -g option and not stripped, then you can do a post-mortem in the debugger and look at variables, stack, etc. Or, just run it in the debugger in the first place. Some consider debugging an art form, but it is one of the most valuable skills you will ever learn as a programmer. Learn how to user your debugger, and utilize it. Many have settings that allow you to detect buffer overflows, uninitialized variables, and a lot of other useful stuff.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.