Thread: Challenging GotW 66's moral

  1. #1
    Registered User
    Join Date
    May 2006
    Posts
    1,579

    Challenging GotW 66's moral

    Hello everyone,


    In GotW #66, one of the moral is the exception handler of constructor should not do any like resource free task. I do not agree. Here is the quoated moral and my code to prove this moral will have memory leak.

    Anything wrong with my analysis?

    http://www.gotw.ca/gotw/066.htm

    Moral #1: Constructor function-try-block handlers have only one purpose -- to translate an exception. (And maybe to do logging or some other side effects.) They are not useful for any other purpose.


    Code:
    class A
    {
    private:
    
    int* p;
    
    public:
    
        A()
        try
        {
            p = new int[10];
    
            // there are some other exceptions here
            
        }
        catch (bad_alloc)
        {
            // do not delete since bad_alloc means memory pointed by p is not allocated
        }
        catch (...)
        {
            // if we do not delete p, there will be memory leak
            // at this point, we are conflicting with Gotw 66's moral 1
            if (p) delete[] p;
        }
    }

    thanks in advance,
    George

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,412
    Here is the quoated moral and my code to prove this moral will have memory leak.
    All you have done is to show that the moral is correct. Your implementation has a memory leak, but that has nothing to do with the moral since you attempt to do more than translate an exception or logging.

    The correct implementation would use a normal try-block, not a function try-block.

    EDIT:
    In fact, the article you linked to states as much:
    "--But wait!" I hear someone interrupting from the middle of the room. "I don't agree with Moral #1. I can think of another possible use for constructor function-try-blocks, namely to free resources allocated in the initializer list or in the constructor body!"

    Sorry, nope. After all, remember that once you get into your constructor try-block's handler, any local variables in the constructor body are also already out of scope, and you are guaranteed that no base subobjects or member objects exist any more, period. You can't even refer to their names. Either the parts of your object were never constructed, or those that were constructed have already been destroyed. So you can't be cleaning up anything that relies on referring to a base or member of the class (and anyway, that's what the base and member destructors are for, right?).
    Last edited by laserlight; 12-27-2007 at 02:33 AM.
    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

  3. #3
    Registered User
    Join Date
    May 2006
    Posts
    1,579
    Hi laserlight,


    Two more comments,

    1.

    Quote Originally Posted by laserlight View Post
    All you have done is to show that the moral is correct. Your implementation has a memory leak
    What is the memory leak in my code? Could you point out please? :-)

    2.

    Quote Originally Posted by laserlight View Post
    any local variables in the constructor body are also already out of scope, and you are guaranteed that no base subobjects or member objects exist any more, period. You can't even refer to their names.
    I am not referring to the names of local variables, but member pointer type member variables. So, the moral you quoted is not the same as what I mentioned above.


    regards,
    George

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,412
    What is the memory leak in my code? Could you point out please? :-)
    Eh, you pointed it out yourself.

    I am not referring to the names of local variables, but member pointer type member variables. So, the moral you quoted is not the same as what I mentioned above.
    I quoted from the same article you quoted. The point Herb Sutter is making in GotW #66 Moral #1 is that you should not be using function try-blocks to do anything other than translating an exception thrown by a base subobject or member object. (With the possible exceptions of logging the exception and other side effects.)

    Your example does just what he said not to do, then you accuse the moral of being wrong. Clearly, this does not make sense.
    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

  5. #5
    Registered User
    Join Date
    May 2006
    Posts
    1,579
    Hi laserlight,


    I do not think my code could cause memory leak. :-)

    What do you think is wrong?

    1. if there is exception, I free in exception handler;
    2. if no exception, I free in destructor.

    Quote Originally Posted by laserlight View Post
    Eh, you pointed it out yourself.

    regards,
    George

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,412
    I do not think my code could cause memory leak. :-)

    What do you think is wrong?

    1. if there is exception, I free in exception handler;
    2. if no exception, I free in destructor.
    Oh, I misread your code. Your code should not cause a memory leak, but it either should not even compile, or should have undefined behaviour. According to Sutter:
    After all, remember that once you get into your constructor try-block's handler, any local variables in the constructor body are also already out of scope, and you are guaranteed that no base subobjects or member objects exist any more, period. You can't even refer to their names.
    Having tested this myself, both the MinGW port of g++ 3.4.5 and MSVC8 allow me to refer to the name of a member object in the try-block's handler, so that contradicts the text. In fact, swapping int for a user defined object with tagged default ctor and dtor, your example shows that there is no memory leak (and of course it compiles).

    My guess is that either Sutter is wrong about that and thus it is also possible to use constructor function try-blocks to free resources allocated in the initializer list or in the constructor body, or Sutter is right and this is in the realm of undefined behaviour, so what I got with both compilers was just a matter of luck. However, the Section 15.3 of the 2003 Edition of the C++ Standard states: "The fully constructed base classes and members of an object shall be destroyed before entering the handler of a function-try-block of a constructor or destructor for that object." So it seems to me that Sutter is indeed correct, and we are just lucky (or unlucky, as the case may be).
    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

  7. #7
    Registered User
    Join Date
    May 2006
    Posts
    1,579
    Thanks laserlight,


    I think you have the same insight as that of Sutter. :-)

    I agree and I will put the delete code in a local try catch handler, other than function try catch handler.

    Quote Originally Posted by laserlight View Post
    Oh, I misread your code. Your code should not cause a memory leak, but it either should not even compile, or should have undefined behaviour. According to Sutter:


    Having tested this myself, both the MinGW port of g++ 3.4.5 and MSVC8 allow me to refer to the name of a member object in the try-block's handler, so that contradicts the text. In fact, swapping int for a user defined object with tagged default ctor and dtor, your example shows that there is no memory leak (and of course it compiles).

    My guess is that either Sutter is wrong about that and thus it is also possible to use constructor function try-blocks to free resources allocated in the initializer list or in the constructor body, or Sutter is right and this is in the realm of undefined behaviour, so what I got with both compilers was just a matter of luck. However, the Section 15.3 of the 2003 Edition of the C++ Standard states: "The fully constructed base classes and members of an object shall be destroyed before entering the handler of a function-try-block of a constructor or destructor for that object." So it seems to me that Sutter is indeed correct, and we are just lucky (or unlucky, as the case may be).

    regards,
    George

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. MFC is Challenging :: C++
    By kuphryn in forum C++ Programming
    Replies: 8
    Last Post: 02-05-2002, 01:33 AM