Thread: Classes and error handling

  1. #16
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> Like this?
    Yes. You might also consider taking the string as a const reference, although that shouldn't be a big deal.

    >> they all have been constructor calls for that type. Right?
    Pretty much, yes. Obviously plain old datatypes don't actually have constructors, but the idea is the same.

    >> So if I throw before allocating, there would still be a memory leak?
    If you throw before allocating, then there would not be a leak. If you throw after allocating, there would be a leak (unless you deallocate before throwing). However, in most cases (at least in your pseudocode) you don't need to do any allocating on your own, so you don't have to worry about it. The ifstream and string classes will clean themselves up.

  2. #17
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    Quote Originally Posted by Prelude
    >I'm not sure if I follow you on this one, Prelude...
    Exceptions are a bulky and time consuming process in C++. As such, they should be reserved for truly abnormal behavior to avoid the overhead and code bloat. Let's assume that giving the user control over something produces a random correct/incorrect result over a controlled sequence. That said, we can expect about 50% of the files that the user wants to open to have some kind of problem that would cause the open to fail (misspelled name, wrong directory, non-existent file, etc...). A failure condition for half of the requests is not abnormal behavior, so throwing an exception isn't the best option for a user controlled file open.
    Speed of execution is rarely a consideration in most cases where you need to open files. It's rare to do anything like opening files in a time-critical section of code (if for no other reason than opening files is itself time-consuming). After a failed open, your program is almost certainly going to be idle and waiting for user input to confirm whether it should abort/retry/whatever, and whether that dialog pops up in 0.05 seconds or 0.07 seconds isn't really a big deal. The user won't visually see a difference.

    In general I think the benefits of throwing an exception outweigh the negligible performance hit.
    You ever try a pink golf ball, Wally? Why, the wind shear on a pink ball alone can take the head clean off a 90 pound midget at 300 yards.

  3. #18
    The larch
    Join Date
    May 2006
    Posts
    3,573
    As for the try block, I hope you don't mean "terminate program here" by means of the terminate function or anything similar. If you want you can log the error and do any cleaning you may feel like... but the proper way to terminate is to rethrow the error afterwards.
    That's what I thought . So the correct way would be
    Code:
    try {
        something = new char[somesize];
    }
    catch (...) {
        //log it
        throw FatalError;
    }
    ... and if user is smart enough, they might even figure out what to do about FatalError?

    As for the speed question, yes, in this particular constructor speed would not matter. However, speed might be a concern if I did exception handling with read/write operations, which might be in loops. I'll just need to test and see if that would be that bad.
    [edit]
    But then. If the first error is encountered, the error handler should exit the loop after all?! Would there be enormous overhead then?
    Last edited by anon; 08-30-2006 at 04:14 PM.

  4. #19
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    You can use "throw" to re-throw the current exception (at least you can in Java, I'm not sure about C++). [edit] Yes, you can do it in C++, I just checked.
    Code:
    #include <iostream>
    
    class e {};
    
    int main() {
        try {
            throw e();
        }
        catch(e x) {
            throw;
        }
        
        return 0;
    }
    No errors.
    [/edit]
    [edit=2] Wait, it's throw() as Mario F. pointed out. Too much Java programming. [/edit]
    Last edited by dwks; 08-30-2006 at 04:29 PM.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  5. #20
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    Quote Originally Posted by anon
    ... and if user is smart enough, they might even figure out what to do about FatalError?
    Nah. No need. You just need to write thow();after the logging stuff.
    Code:
    /* ... */
    catch ( /* ... */ ) {
       // logging code;
       throw();
    }
    
    /* ... */
    That will rethrow the exception and propagate it up in the call stack. Without any proper error handling, the application will terminate.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  6. #21
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    I just tested some code on MS VC++:

    Code:
    #include "windows.h"
    #include <iostream>
    #include <string>
    #include <stdexcept>
    
    
    int Fail(){
    	return 1;
    }
    
    void Throw(){
    	throw std::runtime_error("Failure condition detected!\n");
    }
    
    
    
    int main(int, char**){
    
    	const int count = 10000;
    
    	LARGE_INTEGER time0,time1,time2;
    
    	QueryPerformanceCounter(&time0);
    	for (int i = 0; i < count; i++){
    
    		if (Fail()){
    			std::cout << "Failure condition detected!\n";
    		}
    	}
    	QueryPerformanceCounter(&time1);
    	for (int i = 0; i < count; i++){
    
    		try{
    			Throw();
    		}
    		catch (std::runtime_error s){
    			std::cout << s.what();
    		}
    	}
    	QueryPerformanceCounter(&time2);
    
    	std::cout.flush();
    
    	std::cout << "Error code: " << (time1.QuadPart-time0.QuadPart) << " us" << std::endl;
    	std::cout << "Exception:  " << (time2.QuadPart-time1.QuadPart) << " us" << std::endl;
    
    }
    The results on this test are variable -- multiple runs through the code show almost equal time; sometimes one is faster, sometimes the other.

    Overall, the time difference between a single throw() and a single error return is on the order of 500 nanoseconds (0.0000005 seconds) which in most cases is not going to be your speed-limiting factor.
    Last edited by Cat; 08-30-2006 at 05:25 PM.
    You ever try a pink golf ball, Wally? Why, the wind shear on a pink ball alone can take the head clean off a 90 pound midget at 300 yards.

  7. #22
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Did you optimise your code?

    What you should do is pass -s to g++ to get the equivalent assembly code.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  8. #23
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    Yeah, that was release mode with all optimizations for speed enabled.
    You ever try a pink golf ball, Wally? Why, the wind shear on a pink ball alone can take the head clean off a 90 pound midget at 300 yards.

  9. #24
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Well then it might have optimised it to be the same thing. Which means that it doesn't matter which you use.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

Popular pages Recent additions subscribe to a feed