Error processing using try-catch blocks 
Author Message
 Error processing using try-catch blocks

Hi all,

  I've been trying to understand try-catch blocks in C++, and having some
problems, so in order to try and figure it out, I decided to run the example
from the MSDN documentation shown below.  I ran it exactly as it was
provided, with the one exception (no pun intended!) being that I added an
output statement to the CTest constructor and destructor, so that I could
see when each of them got called.  Here is the code:

#include <iostream.h>

void MyFunc( void );

class CTest
{
public:
  CTest(){ cout << "Entering CTest constructor\n"; };
    ~CTest(){ cout << "Entering CTest destructor\n"; };
  const char *ShowReason() const { return "Exception in CTest class."; }

Quote:
};

class CDtorDemo
{
public:
    CDtorDemo();
    ~CDtorDemo();

Quote:
};

CDtorDemo::CDtorDemo()
{
    cout << "Constructing CDtorDemo." << endl;

Quote:
}

CDtorDemo::~CDtorDemo()
{
    cout << "Destructing CDtorDemo." << endl;

Quote:
}

void MyFunc()
{
    CDtorDemo D;
    cout<< "In MyFunc(). Throwing CTest exception." << endl;
    throw CTest();

Quote:
}

int main()
{
    cout << "In main." << endl;
    try
    {
        cout << "In try block, calling MyFunc()." << endl;
        MyFunc();
    }
    catch( CTest E )
    {
        cout << "In catch handler." << endl;
        cout << "Caught CTest exception type: ";
        cout << E.ShowReason() << endl;
    }
    catch( char *str )
    {
        cout << "Caught some other exception: " << str << endl;
    }
    cout << "Back in main. Execution resumes here." << endl;
    return 0;

Quote:
}

When I ran this, I got the following output:

        In main.
        In try block, calling MyFunc().
        Constructing CDtorDemo.
        In MyFunc(). Throwing CTest exception.
        Entering CTest constructor
        Entering CTest destructor
        Destructing CDtorDemo.
        In catch handler.
        Caught CTest exception type: Exception in CTest class.
        Entering CTest destructor
        Entering CTest destructor
        Back in main. Execution resumes here.

  My question is, can anyone tell me why it is that the CTest CONSTRUCTOR
only gets called ONCE, whereas the CTest DESTRUCTOR gets called THREE
times??  And, if the CTest object's destructor has already been called, then
how is it that the CTest method "ShowReason" can still be called and output
correctly??  This does NOT make sense!

  If anyone could explain this, I would really appreciate it!

  Thanks,
            -- LL



Mon, 08 Dec 2003 07:26:36 GMT  
 Error processing using try-catch blocks
Every C++ class has a default constructor (constructor with no parameters)
and a copy-constructor (a constructor that accepts a reference to the object
of the same type and endeavors to make a copy of this object). If you don't
specify any of those constructors explicitly, compiler is happy to create
them for you. In your case, the compiler created a copy-constructor for
CTest - calls to this constructor (which of course you don't trace) balance
calls to destructor.

Add the following constructor to CTest class:

CTest(const CTest&) {cout<< "Entering CTest copy-constructor\n";}

--
With best wishes,
    Igor Tandetnik


Quote:
> Hi all,

>   I've been trying to understand try-catch blocks in C++, and having some
> problems, so in order to try and figure it out, I decided to run the
example
> from the MSDN documentation shown below.  I ran it exactly as it was
> provided, with the one exception (no pun intended!) being that I added an
> output statement to the CTest constructor and destructor, so that I could
> see when each of them got called.  Here is the code:

> #include <iostream.h>

> void MyFunc( void );

> class CTest
> {
> public:
>   CTest(){ cout << "Entering CTest constructor\n"; };
>     ~CTest(){ cout << "Entering CTest destructor\n"; };
>   const char *ShowReason() const { return "Exception in CTest class."; }
> };

> class CDtorDemo
> {
> public:
>     CDtorDemo();
>     ~CDtorDemo();
> };

> CDtorDemo::CDtorDemo()
> {
>     cout << "Constructing CDtorDemo." << endl;
> }

> CDtorDemo::~CDtorDemo()
> {
>     cout << "Destructing CDtorDemo." << endl;
> }

> void MyFunc()
> {
>     CDtorDemo D;
>     cout<< "In MyFunc(). Throwing CTest exception." << endl;
>     throw CTest();
> }

> int main()
> {
>     cout << "In main." << endl;
>     try
>     {
>         cout << "In try block, calling MyFunc()." << endl;
>         MyFunc();
>     }
>     catch( CTest E )
>     {
>         cout << "In catch handler." << endl;
>         cout << "Caught CTest exception type: ";
>         cout << E.ShowReason() << endl;
>     }
>     catch( char *str )
>     {
>         cout << "Caught some other exception: " << str << endl;
>     }
>     cout << "Back in main. Execution resumes here." << endl;
>     return 0;
> }

> When I ran this, I got the following output:

>         In main.
>         In try block, calling MyFunc().
>         Constructing CDtorDemo.
>         In MyFunc(). Throwing CTest exception.
>         Entering CTest constructor
>         Entering CTest destructor
>         Destructing CDtorDemo.
>         In catch handler.
>         Caught CTest exception type: Exception in CTest class.
>         Entering CTest destructor
>         Entering CTest destructor
>         Back in main. Execution resumes here.

>   My question is, can anyone tell me why it is that the CTest CONSTRUCTOR
> only gets called ONCE, whereas the CTest DESTRUCTOR gets called THREE
> times??  And, if the CTest object's destructor has already been called,
then
> how is it that the CTest method "ShowReason" can still be called and
output
> correctly??  This does NOT make sense!

>   If anyone could explain this, I would really appreciate it!

>   Thanks,
>             -- LL



Mon, 08 Dec 2003 07:36:22 GMT  
 Error processing using try-catch blocks

Quote:
> Every C++ class has a default constructor (constructor with no parameters)

No, only if no other constructors are user-defined. This class has no
default constructor:

class Foo { Foo(int); };

Quote:
> and a copy-constructor (a constructor that accepts a reference to the
object
> of the same type and endeavors to make a copy of this object).

A nitpick: the following class does not have a copy constructor:

class Foo {
//...
private:
    Foo(const Foo&);

Quote:
};

There's a copy constructor declared (so the compiler won't create one), but
it's not defined, so it doesn't exist.


Mon, 08 Dec 2003 08:04:33 GMT  
 Error processing using try-catch blocks
Thanks Igor!  I tried your suggestion, and sure enough, the constructor and
destructor calls were balanced.  Here's the output I got:

In main.
In try block, calling MyFunc().
Constructing CDtorDemo.
In MyFunc(). Throwing CTest exception.
Entering CTest constructor
Entering CTest copy-constructor
Destructing CDtorDemo.
In catch handler.
Caught CTest exception type: Exception in CTest class.
Entering CTest destructor
Entering CTest destructor
Back in main. Execution resumes here.

  The only thing that's still confusing me, though, is that with the
original code, the constructor got called and then the destructor was called
once immediately afterwards - BEFORE the call to "ShowReason" - and then
there were two more calls to the destructor later in the program.  Here, on
the other hand, the constructor gets called, then the copy constructor, THEN
"ShowReason," and AFTER that, are the only two destructor calls!
So, why the difference??

    -- LL


Quote:
> Every C++ class has a default constructor (constructor with no parameters)
> and a copy-constructor (a constructor that accepts a reference to the
object
> of the same type and endeavors to make a copy of this object). If you
don't
> specify any of those constructors explicitly, compiler is happy to create
> them for you. In your case, the compiler created a copy-constructor for
> CTest - calls to this constructor (which of course you don't trace)
balance
> calls to destructor.

> Add the following constructor to CTest class:

> CTest(const CTest&) {cout<< "Entering CTest copy-constructor\n";}

> --
> With best wishes,
>     Igor Tandetnik



> > Hi all,

> >   I've been trying to understand try-catch blocks in C++, and having
some
> > problems, so in order to try and figure it out, I decided to run the
> example
> > from the MSDN documentation shown below.  I ran it exactly as it was
> > provided, with the one exception (no pun intended!) being that I added
an
> > output statement to the CTest constructor and destructor, so that I
could
> > see when each of them got called.  Here is the code:

> > #include <iostream.h>

> > void MyFunc( void );

> > class CTest
> > {
> > public:
> >   CTest(){ cout << "Entering CTest constructor\n"; };
> >     ~CTest(){ cout << "Entering CTest destructor\n"; };
> >   const char *ShowReason() const { return "Exception in CTest class."; }
> > };

> > class CDtorDemo
> > {
> > public:
> >     CDtorDemo();
> >     ~CDtorDemo();
> > };

> > CDtorDemo::CDtorDemo()
> > {
> >     cout << "Constructing CDtorDemo." << endl;
> > }

> > CDtorDemo::~CDtorDemo()
> > {
> >     cout << "Destructing CDtorDemo." << endl;
> > }

> > void MyFunc()
> > {
> >     CDtorDemo D;
> >     cout<< "In MyFunc(). Throwing CTest exception." << endl;
> >     throw CTest();
> > }

> > int main()
> > {
> >     cout << "In main." << endl;
> >     try
> >     {
> >         cout << "In try block, calling MyFunc()." << endl;
> >         MyFunc();
> >     }
> >     catch( CTest E )
> >     {
> >         cout << "In catch handler." << endl;
> >         cout << "Caught CTest exception type: ";
> >         cout << E.ShowReason() << endl;
> >     }
> >     catch( char *str )
> >     {
> >         cout << "Caught some other exception: " << str << endl;
> >     }
> >     cout << "Back in main. Execution resumes here." << endl;
> >     return 0;
> > }

> > When I ran this, I got the following output:

> >         In main.
> >         In try block, calling MyFunc().
> >         Constructing CDtorDemo.
> >         In MyFunc(). Throwing CTest exception.
> >         Entering CTest constructor
> >         Entering CTest destructor
> >         Destructing CDtorDemo.
> >         In catch handler.
> >         Caught CTest exception type: Exception in CTest class.
> >         Entering CTest destructor
> >         Entering CTest destructor
> >         Back in main. Execution resumes here.

> >   My question is, can anyone tell me why it is that the CTest
CONSTRUCTOR
> > only gets called ONCE, whereas the CTest DESTRUCTOR gets called THREE
> > times??  And, if the CTest object's destructor has already been called,
> then
> > how is it that the CTest method "ShowReason" can still be called and
> output
> > correctly??  This does NOT make sense!

> >   If anyone could explain this, I would really appreciate it!

> >   Thanks,
> >             -- LL



Mon, 08 Dec 2003 08:12:44 GMT  
 Error processing using try-catch blocks

Quote:

> Thanks Igor!  I tried your suggestion, and sure enough, the constructor and
> destructor calls were balanced.  Here's the output I got:

> In main.
> In try block, calling MyFunc().
> Constructing CDtorDemo.
> In MyFunc(). Throwing CTest exception.
> Entering CTest constructor
> Entering CTest copy-constructor
> Destructing CDtorDemo.
> In catch handler.
> Caught CTest exception type: Exception in CTest class.
> Entering CTest destructor
> Entering CTest destructor
> Back in main. Execution resumes here.

>   The only thing that's still confusing me, though, is that with the
> original code, the constructor got called and then the destructor was called
> once immediately afterwards - BEFORE the call to "ShowReason" - and then
> there were two more calls to the destructor later in the program.  Here, on
> the other hand, the constructor gets called, then the copy constructor, THEN
> "ShowReason," and AFTER that, are the only two destructor calls!
> So, why the difference??

The compiler has chosen not to make another copy.
When reading TC++PL3 I came across a note stating that an implementation
is free to make as many copies of the exception object as it likes.
So no bets when it comes to copy constructor calls.

Sergei



Mon, 08 Dec 2003 16:04:20 GMT  
 Error processing using try-catch blocks
  Thanks everybody for the help!  I THINK I'm getting a little bit better
understanding of how this all works... although - as is typical with C++, it
seems - there ARE still a few "nagging questions!"  But I at least feel like
maybe I know enough now to get things to work in a more or less predictable
fashion, so that's progress anyway - and maybe someday, the "mysteries" will
all be cleared up!!  As far as I can tell, though, it seems the way to get
things to work reliably is to either (a) define your OWN copy constructors,
or (b) pass by reference, so that copies aren't an issue!

  Thanks again to all who responded!
                                                        -- LL


Quote:
> Try changing the code in this way
>    catch (CTest *E)
> or else
>    catch (CTest &E)
> to avoid the copy of the exception object, and see what
> happens...



Tue, 09 Dec 2003 13:58:02 GMT  
 Error processing using try-catch blocks

Quote:

>  As far as I can tell, though, it seems the way to get
> things to work reliably is to either (a) define your OWN copy constructors,
> or (b) pass by reference, so that copies aren't an issue!

I would put it
(a) AND (b)

VC6.0 makes copies when passing by reference objects of classes
without explicitly defined copy ctors.

Sergei



Tue, 09 Dec 2003 17:51:02 GMT  
 Error processing using try-catch blocks
Quote:
> VC6.0 makes copies when passing by reference objects of classes
> without explicitly defined copy ctors.

I think you're mistaken: the reference object parameters are intended
to not being copied, just like pointers. I mean, in the copy
constructor CMyClass::CMyClass(const CMyClass &ob) the parameter
itself is a reference. If it should be copied then you'd have an
infinite loop.


Tue, 09 Dec 2003 20:02:43 GMT  
 Error processing using try-catch blocks

Quote:

> > VC6.0 makes copies when passing by reference objects of classes
> > without explicitly defined copy ctors.
> I think you're mistaken: the reference object parameters are intended
> to not being copied, just like pointers. I mean, in the copy
> constructor CMyClass::CMyClass(const CMyClass &ob) the parameter
> itself is a reference. If it should be copied then you'd have an
> infinite loop.

I didn't make myself clear. What I meant was that VC makes copies
of exception objects even when you catch them by reference. And
this you can test, just change your original code to catch the exception
by reference.

Sergei



Thu, 11 Dec 2003 03:04:01 GMT  
 
 [ 9 post ] 

 Relevant Pages 

1. The if ~ else block in try~catch block

2. TRY-CATCH vs. try-catch

3. try/catch VS TRY/CATCH

4. Optimizer ignores try-catch block

5. try catch block

6. does atl support try..catch block?(empty inside)

7. Overhead of try-catch blocks?

8. /Og causes intermittent omission of try..catch block

9. nested try/catch block and _set_se_translator

10. can I nest try/catch blocks?

11. try{} catch{} block and Global Optimization

12. Try catch blocks - can multiple methods share a single try/catch combination?

 

 
Powered by phpBB® Forum Software