Thread: Error Handling in Constructor

  1. #1
    Registered User
    Join Date
    Feb 2004
    Posts
    31

    Question Error Handling in Constructor

    Hey,

    Over the past few weeks I've experienced the same dilemma during coding:

    If you want to use the constructor to initialize some class member variables (such as allocating memory), what is the best practice approach to deal with errors?

    I prefer not working with exceptions in my code so I started wondering how one tells the caller that the initialization failed in the constructor. I guess the obvious solution would be to not perform any operations that could potentially fail in the constructor, but this would just lead to extra code when initializing the class:

    Code:
    // Allocate 1024 bytes of memory
    CFoo foo(1024);
    
    OR
    
    CFoo foo;
    if (!foo.Allocate(1024))
         ...
    
    OR
    
    CFoo foo(1024);
    if (foo.InitFailed())
         ...
    As is evident from the code snippet above, the second example requires two lines of code compared to a single line in the first example. The last example is just a slight variation on the second example, although the initialization now takes place in the constructor whereas the success of the initialization is verified later on in the second function call.

    When not using exceptions I guess there is no alternative to doing multiple function calls if you want to make sure the object was created and initialized successfully. The question, however, is which approach is the best to use...
    Last edited by Halloko; 08-30-2006 at 05:16 PM.
    Parts of my days are spent bug fixing...err. I’m sorry...I’ve just been reminded that we don’t have bugs. We have undocumented features. (Jonathan Ackley on Monkey Island 3)

  2. #2
    すまん Hikaru's Avatar
    Join Date
    Aug 2006
    Posts
    46
    Quote Originally Posted by Halloko
    If you want to use the constructor to initialize some class member variables (such as allocating memory), what is the best practice approach to deal with errors?
    I can only think of two ways. First, you can throw an exception. Or you can set a flag or something that code using the class can test for. fstreams use the flag, and I can't think of a C++ class that throws an exception so a flag sounds like the best way.
    Code:
    #include <fstream>
    #include <iostream>
    
    int main()
    {
        std::ifstream is("myFile.txt");
    
        if (!is)
        {
            std::cerr << "File not open!\n";
        }
    
        return 0;
    }

  3. #3
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    There is an in-depth discussion about exceptions versus error flags currently going on in the Classes and error handling thread.

    I would re-consider the use of exceptions. If you don't use exceptions, I would prefer to use option #3, since if the class user forgets to call the second function, the code will still work when the initialization worked. In either scenario, a failure to call the second function will be an error if the initialization is going to fail.

    Also, in C++ you rarely actually need to do allocations directly in the constructors of your objects. You should be using tools that handle memory management for you (like string or vector). In those cases you will be forced to use exceptions for memory issues unless you specifically force new to not throw an exception when it fails.

  4. #4
    Registered User
    Join Date
    Feb 2004
    Posts
    31
    Quote Originally Posted by Daved
    I would re-consider the use of exceptions.
    I'm a bit old-fashioned (or whatever you'd like to call it). I prefer actually checking return values rather than cluttering my code with try/catch statements.

    Quote Originally Posted by Daved
    If you don't use exceptions, I would prefer to use option #3, since if the class user forgets to call the second function, the code will still work when the initialization worked. In either scenario, a failure to call the second function will be an error if the initialization is going to fail.
    I completely agree.

    Quote Originally Posted by Daved
    Also, in C++ you rarely actually need to do allocations directly in the constructors of your objects. You should be using tools that handle memory management for you (like string or vector).
    So you're saying that I should refrain from using new/delete?

    Quote Originally Posted by Daved
    In those cases you will be forced to use exceptions for memory issues unless you specifically force new to not throw an exception when it fails.
    That leads to an interesting question (for my part). What happens if you force new to not throw an exception when it fails? Does it just return NULL?
    Parts of my days are spent bug fixing...err. I’m sorry...I’ve just been reminded that we don’t have bugs. We have undocumented features. (Jonathan Ackley on Monkey Island 3)

  5. #5
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    So you're saying that I should refrain from using new/delete?
    No, you should just use containers that do the allocating for you.

    That leads to an interesting question (for my part). What happens if you force new to not throw an exception when it fails? Does it just return NULL?
    Yes.
    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.

  6. #6
    すまん Hikaru's Avatar
    Join Date
    Aug 2006
    Posts
    46
    Quote Originally Posted by Halloko
    I prefer actually checking return values rather than cluttering my code with try/catch statements.
    I think that if you do it right, there won't be many try/catch statements so checking return values is the one that clutters your code.
    Quote Originally Posted by Halloko
    What happens if you force new to not throw an exception when it fails? Does it just return NULL?
    It looks like it.

  7. #7
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Quote Originally Posted by dwks
    No, you should just use containers that do the allocating for you.
    If you don't want exeptions you would need to specify your own allocator though.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  8. #8
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> I prefer actually checking return values rather than cluttering my code with try/catch statements.
    Using exceptions well generally means there aren't a lot of try/catch blocks. They are for exceptional situations (e.g. out of memory) and should only be caught in places that can do something about it or terminate gracefully. It's obviously your choice, but in this situation, assuming the errors you are worried about are like out of memory errors, the code with exceptions (option #1) is a lot less cluttered than the one without.

    If you're talking about more common errors (like a file open failure), then exceptions might not be the way to go.

    >> So you're saying that I should refrain from using new/delete?
    It depends, but in most circumstances, yes. If you are "old-fashioned" then it might take some getting used to, but modern C++ has a lot of tools that handle these things for you so you don't have to put all the error checking and memory management into your own code and you don't accidentally do it wrong.

  9. #9
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    Quote Originally Posted by Halloko
    I'm a bit old-fashioned (or whatever you'd like to call it). I prefer actually checking return values rather than cluttering my code with try/catch statements.
    This is not a good argument. You don't simply pick as if you were in a supermarket choosing oranges by color and size. It's not a matter of taste. It's a matter of good practice and code correctness.

    While it may be debatable whether one should use exceptions here or there, the reason is never because "I don't like them" or "I'm old fashioned". Adapt, or fail.

    It's that simple.
    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.

  10. #10
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    Quote Originally Posted by Halloko
    I'm a bit old-fashioned (or whatever you'd like to call it). I prefer actually checking return values rather than cluttering my code with try/catch statements.
    In general, you need far fewer try...catch statements than you do error-checking lines.

    In fact, that's the best reason in favor of using try...catch, you can often get a massive reduction in the amount of code you need to write to handle errors.
    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.

  11. #11
    Registered User
    Join Date
    Feb 2004
    Posts
    31
    Quote Originally Posted by dwks
    No, you should just use containers that do the allocating for you.
    Like vectors and strings, as Daved pointed out? But isn't that pretty much refraining from using new/delete directly?

    Quote Originally Posted by Hikaru
    I think that if you do it right, there won't be many try/catch statements so checking return values is the one that clutters your code..
    I disagree. Using try/catch blocks remove your focus from the actual flow of your program and you could end up with several such blocks for every single thing you do as you would need to clean up your traces in the correct order. Anyway, that's not the point of this post
    Parts of my days are spent bug fixing...err. I’m sorry...I’ve just been reminded that we don’t have bugs. We have undocumented features. (Jonathan Ackley on Monkey Island 3)

  12. #12
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Like vectors and strings, as Daved pointed out? But isn't that pretty much refraining from using new/delete directly?
    Yeah, I guess it is.
    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.

  13. #13
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    Quote Originally Posted by Halloko
    I disagree. Using try/catch blocks remove your focus from the actual flow of your program and you could end up with several such blocks for every single thing you do as you would need to clean up your traces in the correct order. Anyway, that's not the point of this post
    If you are finding yourself needing to clean up using try..catch repeatedly, chances are you should be using containers for your pointers, which will automatically do the cleanup in their destructors.

    The beauty of exceptions is a single try...catch could deal with, say, thirty possible error conditions. You do need to write your code to not leak memory in the event of an exception, but it's not hard to make cleanup code happen in destructors (which means -- automatically).
    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.

  14. #14
    Registered User
    Join Date
    Feb 2004
    Posts
    31
    Quote Originally Posted by Daved
    >> I prefer actually checking return values rather than cluttering my code with try/catch statements.
    Using exceptions well generally means there aren't a lot of try/catch blocks. They are for exceptional situations (e.g. out of memory) and should only be caught in places that can do something about it or terminate gracefully. It's obviously your choice, but in this situation, assuming the errors you are worried about are like out of memory errors, the code with exceptions (option #1) is a lot less cluttered than the one without.

    If you're talking about more common errors (like a file open failure), then exceptions might not be the way to go.
    Yes, I was talking about using exceptions for everything. And I definitely agree that a mixed approach is the way to go. For this particular case, using exceptions definitely seems to be the less cluttered choice.

    Quote Originally Posted by Daved
    >> So you're saying that I should refrain from using new/delete?
    It depends, but in most circumstances, yes. If you are "old-fashioned" then it might take some getting used to, but modern C++ has a lot of tools that handle these things for you so you don't have to put all the error checking and memory management into your own code and you don't accidentally do it wrong.
    Hmm, I'd definitely want to have a peek at that. I've always just used new and delete.
    Parts of my days are spent bug fixing...err. I’m sorry...I’ve just been reminded that we don’t have bugs. We have undocumented features. (Jonathan Ackley on Monkey Island 3)

  15. #15
    Registered User
    Join Date
    Feb 2004
    Posts
    31
    Quote Originally Posted by Mario F.
    This is not a good argument. You don't simply pick as if you were in a supermarket choosing oranges by color and size. It's not a matter of taste. It's a matter of good practice and code correctness.

    While it may be debatable whether one should use exceptions here or there, the reason is never because "I don't like them" or "I'm old fashioned". Adapt, or fail.
    That wasn't really what I meant by "old-fashioned". I merely meant that I did things the c-style way, that is, not using exceptions when I could avoid it.

    As has become evident in this thread, for this particular question using exceptions is the way to go. But as you say yourself, when to use exceptions and not is debatable, but I've found that using c-style error checking rather than exceptions for most common cases such as file handling is the best approach.. for me.
    Parts of my days are spent bug fixing...err. I’m sorry...I’ve just been reminded that we don’t have bugs. We have undocumented features. (Jonathan Ackley on Monkey Island 3)

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 1
    Last Post: 06-10-2008, 08:38 PM
  2. C++ have a constructor call another constructor
    By QuestionC in forum C++ Programming
    Replies: 4
    Last Post: 05-17-2007, 01:59 AM
  3. Replies: 3
    Last Post: 03-26-2006, 12:59 AM
  4. Need help in classes
    By LBY in forum C++ Programming
    Replies: 11
    Last Post: 11-26-2004, 04:50 AM
  5. Constructor with Parameter not Firing
    By BillBoeBaggins in forum Windows Programming
    Replies: 4
    Last Post: 08-26-2004, 02:17 PM