try object out of scope before catch?

Discussion in 'C++' started by Jackson A. Marshall, Jan 11, 2005.

  1. I have a been testing the try/catch exception mechanism
    (as implemented by DigitalMars) and found that if I
    throw an object its dtor gets called 3 times, if I throw
    a reference its dtor gets called twice - and so it seems
    practical to instantiate an object and throw its address,
    and sure enough, its dtor gets called only once.

    This is part of the Test class implementation (contains only
    one data member: "int n" ):

    volatile int count = 0;

    // Constructor
    Test::Test() : n(0) {
    ++::count;
    std::cout << " Test(" << ::count << ")\n";
    }

    // Constructor
    Test::Test(int nn) : n(nn) {
    ++::count;
    std::cout << " Test(" << ::count << ")\n";
    }

    // Destructor
    Test::~Test() {
    std::cout << "~Test(" << ::count << ")\n";
    --::count;
    }

    // e.g. Test1 += Test2;
    const Test& Test::eek:perator+=(const Test& rhs) {
    std::cout << "operator+=(Test&)\n";
    if(this == &rhs) {
    Except ex("operator+= self assignment!");
    throw( &ex );
    }
    n += rhs.n;
    return *this;
    }

    The Except class implementation..

    volatile int except = 0;

    // Constructor
    Except::Except(const char* msg = 0) : data(msg) {
    ++::except;
    std::cout << " Except(" << ::except << ")\n";
    }

    // Destructor
    Except::~Except() {
    std::cout << "~Except(" << ::except << ")\n";
    --::except;
    }

    // access data
    const char* Except::Get() { return data; }


    int main() {
    Test t;
    try { t += t; }
    catch( Except* e ) {
    cout << "Throw() caught: " << e->Get() << "\n";
    return -1;
    }
    }

    Output:
    ======
    Test(1)
    operator+=(Test&)
    Except(1)
    ~Except(1)
    Throw() caught: operator+= self assignment!
    ~Test(1)

    But this implies that Except goes out of scope before
    the throw is caught. I would have liked to have seen:

    Test(1)
    operator+=(Test&)
    Except(1)
    Throw() caught: operator+= self assignment!
    ~Except(1)
    ~Test(1)

    Anyone comments?

    TIA
    >jam

    --
    "Capitalism is the extraordinary belief that the
    nastiest of men, for the nastiest of reasons, will
    somehow work for the benefit of us all."
    [John Maynard Keynes]
    Jackson A. Marshall, Jan 11, 2005
    #1
    1. Advertising

  2. Jackson A. Marshall wrote:
    > I have a been testing the try/catch exception mechanism
    > (as implemented by DigitalMars) and found that if I
    > throw an object its dtor gets called 3 times, if I throw
    > a reference its dtor gets called twice - and so it seems
    > practical to instantiate an object and throw its address,
    > and sure enough, its dtor gets called only once.
    >
    > This is part of the Test class implementation (contains only
    > one data member: "int n" ):
    >

    [...]
    >
    > Anyone comments?


    Here is a comment: regarding your code and the sequence of d-tors,
    you're throwing an address of a local variable. It gets destroyed
    before you catch it. When you after catching the value of the
    pointer attempt to use it, you get undefined behavour.

    And also your 'Test' class doesn't seem to have any copy c-tor
    implemented, thus making it impossible for you to track copy
    construction (not that you should expect any, but still).

    If you want to throw by an address (pointer), you have to use
    either a global object (that survives the stack unwinding) or
    a dynamic object (use 'new'). Of course, it's better to throw
    a temporary object and catch by a const reference.

    V
    Victor Bazarov, Jan 11, 2005
    #2
    1. Advertising

  3. "Victor Bazarov" <> wrote in message news:F8REd.35036$01.us.to.verio.net...
    > Jackson A. Marshall wrote:
    > > I have a been testing the try/catch exception mechanism
    > > (as implemented by DigitalMars) and found that if I
    > > throw an object its dtor gets called 3 times, if I throw
    > > a reference its dtor gets called twice - and so it seems
    > > practical to instantiate an object and throw its address,
    > > and sure enough, its dtor gets called only once.
    > >
    > > This is part of the Test class implementation (contains only
    > > one data member: "int n" ):
    > >

    > [...]
    > >
    > > Anyone comments?

    >
    > Here is a comment: regarding your code and the sequence of d-tors,
    > you're throwing an address of a local variable. It gets destroyed
    > before you catch it. When you after catching the value of the
    > pointer attempt to use it, you get undefined behavour.
    >
    > And also your 'Test' class doesn't seem to have any copy c-tor
    > implemented, thus making it impossible for you to track copy
    > construction (not that you should expect any, but still).
    >
    > If you want to throw by an address (pointer), you have to use
    > either a global object (that survives the stack unwinding) or
    > a dynamic object (use 'new'). Of course, it's better to throw
    > a temporary object and catch by a const reference.


    Thanks V

    I do have a copy-ctor, just didn't show it:

    // Copy Constructor
    Test::Test(Test& t) : n(t.n) {
    ++::count;
    std::cout << " Test(" << ::count << ") Copy-Ctor\n";
    }

    Using "new" :

    // e.g. Test1 += Test2;
    const Test& Test::eek:perator+=(const Test& rhs) {
    std::cout << "operator+=(Test&)\n";
    if(this == &rhs) {
    Except* ex = new Except("operator+= self assignment!");
    throw( ex );
    }
    n += rhs.n;
    return *this;
    }

    // copy ctor: pass by value
    void test1(Test a) {}

    int main() {
    Test t;
    test1(t); // copy ctor
    cout << "\n";

    try { t += t; }
    catch( Except* e) {
    cout << "Throw() caught: " << e->Get() << "\n";
    delete e;
    return -1;
    }
    }

    Output:
    =====
    Test(1)
    Test(2) Copy-Ctor
    ~Test(2)

    operator+=(Test&)
    Except(1)
    Throw() caught: operator+= self assignment!
    ~Except(1)
    ~Test(1)
    ===============

    What do you mean by (and how do I construct) a "temporary object"?

    >jam
    Jackson A. Marshall, Jan 11, 2005
    #3
  4. Jackson A. Marshall wrote:
    > [...]
    > What do you mean by (and how do I construct) a "temporary object"?


    Try

    const Test& Test::eek:perator+=(const Test& rhs) {
    std::cout << "operator+=(Test&)\n";
    if (this == &rhs)
    throw(Except("operator+= self assignment!")); // temporary

    n += rhs.n;
    return *this;
    }
    ...
    int main() {
    Test t;
    try { t += t; }
    catch(Except const &e) {
    cout << "Caught " << e.Get() << endl;
    }
    return -1;
    }

    V
    Victor Bazarov, Jan 11, 2005
    #4
  5. "Victor Bazarov" <> wrote in message news:JhSEd.35044$01.us.to.verio.net...
    > Jackson A. Marshall wrote:
    > > [...]
    > > What do you mean by (and how do I construct) a "temporary object"?

    >
    > Try
    >
    > const Test& Test::eek:perator+=(const Test& rhs) {
    > std::cout << "operator+=(Test&)\n";
    > if (this == &rhs)
    > throw(Except("operator+= self assignment!")); // temporary
    >
    > n += rhs.n;
    > return *this;
    > }
    > ...
    > int main() {
    > Test t;
    > try { t += t; }
    > catch(Except const &e) {
    > cout << "Caught " << e.Get() << endl;
    > }
    > return -1;
    > }


    Thanks V

    I have implemented the code changes as you suggest.

    Test(1)
    operator+=(Test&)
    Except(1)
    ~Except(1)
    Throw() caught: operator+= self assignment!
    ~Except(0)
    ~Test(1)

    ...but this is incorrect with 2 Except dtors!

    >jam
    Jackson A. Marshall, Jan 11, 2005
    #5
  6. Jackson A. Marshall wrote:
    > "Victor Bazarov" <> wrote in message news:JhSEd.35044$01.us.to.verio.net...
    >
    >>Jackson A. Marshall wrote:
    >>
    >>>[...]
    >>>What do you mean by (and how do I construct) a "temporary object"?

    >>
    >>Try
    >>
    >> const Test& Test::eek:perator+=(const Test& rhs) {
    >> std::cout << "operator+=(Test&)\n";
    >> if (this == &rhs)
    >> throw(Except("operator+= self assignment!")); // temporary
    >>
    >> n += rhs.n;
    >> return *this;
    >> }
    >> ...
    >> int main() {
    >> Test t;
    >> try { t += t; }
    >> catch(Except const &e) {
    >> cout << "Caught " << e.Get() << endl;
    >> }
    >> return -1;
    >> }

    >
    >
    > Thanks V
    >
    > I have implemented the code changes as you suggest.
    >
    > Test(1)
    > operator+=(Test&)
    > Except(1)
    > ~Except(1)
    > Throw() caught: operator+= self assignment!
    > ~Except(0)
    > ~Test(1)
    >
    > ..but this is incorrect with 2 Except dtors!


    Are you sure that you got every Except's _constructor_ accounted for?
    What about the copy constructor?
    Victor Bazarov, Jan 11, 2005
    #6
  7. "Victor Bazarov" <> wrote in message news:7LTEd.35055$01.us.to.verio.net...
    >
    > Are you sure that you got every Except's _constructor_ accounted for?
    > What about the copy constructor?


    Many thanks V

    I didn't have an Except copy-ctor, but do now :

    // Copy Constructor
    Except::Except( const Except& ex) : data(ex.data) {
    ++::except;
    std::cout << " Except(" << ::except << ") Copy-Ctor\n";
    }

    Output:
    Test(1)
    operator+=(Test&)
    Except(1)
    Except(2) Copy-Ctor
    ~Except(2)
    Throw() caught: operator+= self assignment!
    ~Except(1)
    ~Test(1)

    Thanks again
    >jam
    Jackson A. Marshall, Jan 11, 2005
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. bienwell
    Replies:
    4
    Views:
    3,720
    bienwell
    May 27, 2005
  2. John Salerno
    Replies:
    20
    Views:
    829
    John Salerno
    Aug 11, 2006
  3. barcaroller

    try/catch scope question...

    barcaroller, Sep 17, 2007, in forum: C++
    Replies:
    3
    Views:
    3,041
    red floyd
    Sep 18, 2007
  4. Replies:
    34
    Views:
    899
    Alf P. Steinbach
    Dec 2, 2007
  5. Replies:
    35
    Views:
    919
    Alf P. Steinbach
    Dec 2, 2007
Loading...

Share This Page