Thread: Exception safe constructor/destructor

  1. #16
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    You can only declare/use it within the scope of the try block. Outside of that it doesn't exist. At any rate, the whole point of exceptions is to allow some higher level of code to handle the problem, so in most cases you won't even need to put the code in a try block to begin with.

  2. #17
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by TriKri View Post
    So...

    How do you then create an object of a class which constructors throw exceptions? According to what you say, the object doesn't exist, so you can't use it. In other words, code trying to use it will produce compile time errors?
    If the constructor throws, then the object will never exist, so you cannot use it.
    However, note that if the constructor can throw, but it does not, since no error was encountered, then you can use the object.
    Essentially you would just use it as normally below where you created it, inside the try blocks and before the catch blocks, if any.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #18
    Algorithm engineer
    Join Date
    Jun 2006
    Posts
    286
    Maybe exceptions are not supposed to be used as often as I have thought. Since an exception always breaks the scope, you cannot use an object if it's constructors throws exceptions. Consider the following scenario:

    Code:
    void MyFn() {
        MyClass MyObj();
        ... //A lot of code that may use MyObj, depending on the result of the constructor call
    }
    Now, if the default constructor can throw an exception, you would have to wrap it in a try block:

    Code:
    void MyFn() {
        try {
            MyClass MyObj();
            ... //A lot of code that uses MyObj
        }
        catch (ExceptionType exception) {
            ... //A lot of more code (doesn't use MyObj)
        }
    }
    What happens here is that we will have to write the code two times. One time in the try block (since we want to use MyObj before it goes out of scope), and one time outside of the try block (since we still want to run the code if the constructor fails). The amount of code will almost double.

    So my thought was that, if you for example want the thing that caused the exception to be acceptable (i.e. you want the program flow to continue in spite of it, and that not everything just bailes out), maybe you shouldn't use an exception. Maybe one should use some other method instead, like indicating in some way the result of the constructor call (typically a flag would be used), rather than having to leave the scope due to an exception.

    What are your thoughts about this?

    I also assume that if the constructor throws, the object will never have existed, hence the destructor won't be called.
    Come on, you can do it! b( ~_')

  4. #19
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Essentially, yes, I think you have a point in what you say.
    Exceptions are good if you have a large block of code that depends on the former lines to execute without problems.
    If not, then you might consider return types.

    You could pass in a status variable, eg a bool to the constructor which will set it to false or true depending on whether it failed or not. I do not know if such things are considered good practice or not, especially since if the constructor fails, the object will essentially become a zombie object - eg an object that should never be used.
    I would think that exceptions are the only good way of handling this type of situation. You are not required to put try around a large block of code. It could be a single line if you will.

    Also, if the object is never constructed, then the destructor will not be called since the object was never constructed in the first place.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #20
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by TriKri
    Since an exception always breaks the scope, you cannot use an object if it's constructors throws exceptions.
    Yes, and thus if it does not make sense for an object to be used since it cannot be sensibly constructed, you should throw an exception in the relevant constructor. An alternative is to construct the object anyway but in some kind of error state, then leave it up to the caller to check if there is an error (e.g., this is how the standard library I/O stream classes normally work). Yet another alternative is to use two stage construction, where you first create the object then initialise it by calling some function, thus the return value of the function can be an error code.

    Quote Originally Posted by TriKri
    Consider the following scenario:
    This declares a function that takes no arguments and returns a MyClass object:
    Code:
    MyClass MyObj();
    Quote Originally Posted by TriKri
    Now, if the default constructor can throw an exception, you would have to wrap it in a try block:
    The problem is with what you want to do: "A lot of code that may use MyObj, depending on the result of the constructor call". It does not make sense to use MyObj if the constructor fails. If it makes sense, then the constructor should not fail.

    Quote Originally Posted by TriKri
    What happens here is that we will have to write the code two times. One time in the try block (since we want to use MyObj before it goes out of scope), and one time outside of the try block (since we still want to run the code if the constructor fails). The amount of code will almost double.
    Yet, even if you want to do something as insensible as you currently want this duplication is not a must: the duplicated code can be moved to a function.

    Quote Originally Posted by TriKri
    So my thought was that, if you for example want the thing that caused the exception to be acceptable (i.e. you want the program flow to continue in spite of it, and that not everything just bailes out), maybe you shouldn't use an exception. Maybe one should use some other method instead, like indicating in some way the result of the constructor call (typically a flag would be used), rather than having to leave the scope due to an exception.
    Yes. However, note that your example supposes that you want to use MyObj even if its constructor fails. More likely, you want to recover from this failure, or at least log it, and the recovery will not involve MyObj, thus the code in the catch block will not be a duplicate of the rest of the code in the try block, and in fact could well be in some function that calls this one.

    Quote Originally Posted by TriKri
    I also assume that if the constructor throws, the object will never have existed, hence the destructor won't be called.
    Yes. I suggest that you read GotW #66: Constructor Failures.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  6. #21
    Algorithm engineer
    Join Date
    Jun 2006
    Posts
    286
    Okay. I came to think about this since I'm defining a class and I was wondering if the constructors should be allowed to throw exceptions or not. But what seems to be the case, is that throwing exceptions in constructors is generally accepted, so I will allow the constructors to throw exceptions.

    What I meant by "a lot of code that may use MyObj, depending on the result of the constructor call", is that it can use it if the constructor succeeds, but it shouldn't otherwise. The thing is that the code can be a mixture of code that don't use MyObj, and code that does (if the constructor succeeds), hence it could be inseparable, at least potentially. Maybe it never occurs, I was just thinking of what could potentially cause a problem. As you say, the code can probably be placed in another function too.

    Alternatively, one can use a MyClass*, and create the object with new, and when the try block is left, the object isn't lost. But this feels like a workaround, especially since new could fail too.

    Thanks for the replies!
    Come on, you can do it! b( ~_')

  7. #22
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Anything whose scope is inside the try block will disappear when it ends. But you are making workarounds.
    In your try block, you should put code that depends on the code above to succeed in order to execute. In that case, the code will be skipped if one line of code fails.
    If you think you can recover from something, then you should put a local try block around that which you can recover from. So even if you already have on instance of class X and you fail to create a new instance of class X, you can still set a pointer to the already existing instance of class X.
    Of course, the pointer in question here must be outside the local try block.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #23
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    The thing is that the code can be a mixture of code that don't use MyObj, and code that does (if the constructor succeeds), hence it could be inseparable, at least potentially.
    That sounds extremely contrived. Do you have a concrete example of such code?
    The only case I can think of is opening a log that simply shouldn't be written to if it can't be opened.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  9. #24
    Algorithm engineer
    Join Date
    Jun 2006
    Posts
    286
    Quote Originally Posted by CornedBee View Post
    That sounds extremely contrived. Do you have a concrete example of such code?
    No, I haven't; I just thought that maybe, it can happen. That was why I went here to see what you thought about it; I mean, if there is any potential problems that can arise, someone here must know about them.

    But thank you once again for your replies.
    Come on, you can do it! b( ~_')

  10. #25
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    I cannot see that such a situation like yours can occur.
    You would naturally separate code that relies on the object that you construct and that which does not. And you would also separate code that relies on the object being constructed and code that does not.
    In all those cases, the duplicate code problem should never occur.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Exception handling in a large project
    By EVOEx in forum C++ Programming
    Replies: 7
    Last Post: 01-25-2009, 07:33 AM
  2. exception handling
    By coletek in forum C++ Programming
    Replies: 2
    Last Post: 01-12-2009, 05:28 PM
  3. using swap to make assignment operator exception safe
    By George2 in forum C++ Programming
    Replies: 9
    Last Post: 01-10-2008, 06:32 AM
  4. Bjarne's exception safe sample
    By George2 in forum C++ Programming
    Replies: 13
    Last Post: 12-28-2007, 05:38 PM
  5. Signal and exception handling
    By nts in forum C++ Programming
    Replies: 23
    Last Post: 11-15-2007, 02:36 PM