Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Not what I expected from some exception code (throw/try/catch)

Reply
Thread Tools

Not what I expected from some exception code (throw/try/catch)

 
 
stevewilliams2004@comcast.net
Guest
Posts: n/a
 
      07-16-2007
I was wondering if someone could explain the output I am getting for
the program below. What I expected from the main program output was
"Cat" but instead I see "Mammal". The output is also included below.
I got the same results with GCC 3.4.4 under cygwin as with MSDev
studio 2003. Even stranger to me, if I change the catch statement to
catch a Cat instead of a Mammal, the program crashes in the catch
body, during the call to m.MyType(). Thanks for any explanations in
advance.

Program:

#include <iostream>
using namespace std;

class Mammal
{
public:
Mammal()
{
cout << "Constructing Mammal @ " << this << endl;
}
Mammal(const Mammal& source)
{
cout << "Copy Constructing Mammal @ " << this << " from " <<
&source << endl;
}
~Mammal()
{
cout << "Destructing Mammal @ " << this << endl;
}
virtual const char* MyType()
{
return "Mammal";
}
};
class Cat : public Mammal
{
public:
Cat()
{
cout << "Constructing Cat @ " << this << endl;
}
Cat(const Cat& source)
{
cout << "Copy Constructing Cat @ " << this << " from " <<
&source << endl;
}
~Cat()
{
cout << "Destructing Cat @ " << this << endl;
}

virtual const char* MyType()
{
return "Cat";
}
};

int main(int argc, char *argv[])
{
Cat fluffy;
Mammal &fluffyRef = fluffy;
try
{
throw fluffyRef;
}
catch (Mammal &m)
{
cout << "Caught a " << m.MyType() << endl;
return 0;
}
cout << "Nothing Caught" << endl;
return 0;
}

Output:

Steve@nessus /cygdrive/f/dev/src/TestWorkspace
$ ./TestWorkspace.exe
Constructing Mammal @ 0x22ccc0
Constructing Cat @ 0x22ccc0
Copy Constructing Mammal @ 0xc306d8 from 0x22ccc0
Caught a Mammal
Destructing Mammal @ 0xc306d8
Destructing Cat @ 0x22ccc0
Destructing Mammal @ 0x22ccc0

 
Reply With Quote
 
 
 
 
Alf P. Steinbach
Guest
Posts: n/a
 
      07-16-2007
* http://www.velocityreviews.com/forums/(E-Mail Removed):
> I was wondering if someone could explain the output I am getting for
> the program below. What I expected from the main program output was
> "Cat" but instead I see "Mammal". The output is also included below.
> I got the same results with GCC 3.4.4 under cygwin as with MSDev
> studio 2003. Even stranger to me, if I change the catch statement to
> catch a Cat instead of a Mammal, the program crashes


It would, yes, because the exception is then not caught and propagates
out of "main".


> in the catch
> body, during the call to m.MyType().


This I believe is a hypothesis of yours, and an incorrect one.


> Thanks for any explanations in
> advance.
>
> Program:
>
> #include <iostream>
> using namespace std;
>
> class Mammal
> {
> public:
> Mammal()
> {
> cout << "Constructing Mammal @ " << this << endl;
> }
> Mammal(const Mammal& source)
> {
> cout << "Copy Constructing Mammal @ " << this << " from " <<
> &source << endl;
> }
> ~Mammal()
> {
> cout << "Destructing Mammal @ " << this << endl;
> }
> virtual const char* MyType()
> {
> return "Mammal";
> }
> };
> class Cat : public Mammal
> {
> public:
> Cat()
> {
> cout << "Constructing Cat @ " << this << endl;
> }
> Cat(const Cat& source)
> {
> cout << "Copy Constructing Cat @ " << this << " from " <<
> &source << endl;
> }
> ~Cat()
> {
> cout << "Destructing Cat @ " << this << endl;
> }
>
> virtual const char* MyType()
> {
> return "Cat";
> }
> };
>
> int main(int argc, char *argv[])
> {
> Cat fluffy;
> Mammal &fluffyRef = fluffy;
> try
> {
> throw fluffyRef;


Formally, this copy constructs a Mammal to some Mammal instance (the
exception object) provided by the runtime support.

C++ "throw" is by value.


> }
> catch (Mammal &m)


If you don't intend to modify the object, catch by reference to const.
That way you document your intentions, in the source code. Which is
generally the best place to document such low-level details.


> {
> cout << "Caught a " << m.MyType() << endl;
> return 0;
> }
> cout << "Nothing Caught" << endl;
> return 0;
> }


Hth.,

- Alf

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
 
Reply With Quote
 
 
 
 
Kai-Uwe Bux
Guest
Posts: n/a
 
      07-16-2007
(E-Mail Removed) wrote:

> I was wondering if someone could explain the output I am getting for
> the program below. What I expected from the main program output was
> "Cat" but instead I see "Mammal". The output is also included below.
> I got the same results with GCC 3.4.4 under cygwin as with MSDev
> studio 2003. Even stranger to me, if I change the catch statement to
> catch a Cat instead of a Mammal, the program crashes in the catch
> body, during the call to m.MyType(). Thanks for any explanations in
> advance.
>
> Program:
>
> #include <iostream>
> using namespace std;
>
> class Mammal
> {
> public:
> Mammal()
> {
> cout << "Constructing Mammal @ " << this << endl;
> }
> Mammal(const Mammal& source)
> {
> cout << "Copy Constructing Mammal @ " << this << " from " <<
> &source << endl;
> }
> ~Mammal()
> {
> cout << "Destructing Mammal @ " << this << endl;
> }
> virtual const char* MyType()
> {
> return "Mammal";
> }
> };
> class Cat : public Mammal
> {
> public:
> Cat()
> {
> cout << "Constructing Cat @ " << this << endl;
> }
> Cat(const Cat& source)
> {
> cout << "Copy Constructing Cat @ " << this << " from " <<
> &source << endl;
> }
> ~Cat()
> {
> cout << "Destructing Cat @ " << this << endl;
> }
>
> virtual const char* MyType()
> {
> return "Cat";
> }
> };
>
> int main(int argc, char *argv[])
> {
> Cat fluffy;
> Mammal &fluffyRef = fluffy;
> try
> {
> throw fluffyRef;


You throw a Mamal. At this point, a temporary Mamal is created and
initialized from fluffyRef, which involves slicing. See [15.1/3]:

A throw-expression initializes a temporary object, called the exception
object, the type of which is determined by removing any top-level
cv-qualifiers from the static type of the operand of throw and adjusting
the type from ?array of T? or ?function returning T? to ?pointer to T?
or ?pointer to function returning T?, respectively.

Note that the _static type_ is used for the temporary.

Also note that a temporary copy is needed since the original is a local
object that has to go down during stack unwinding.


> }
> catch (Mammal &m)


At this point, the temporary implicitly created in the throw() is used to
initialize the Mamal& here. Since slicing already happened, you don't get a
Cat.

> {
> cout << "Caught a " << m.MyType() << endl;
> return 0;
> }
> cout << "Nothing Caught" << endl;
> return 0;
> }
>
> Output:
>
> Steve@nessus /cygdrive/f/dev/src/TestWorkspace
> $ ./TestWorkspace.exe
> Constructing Mammal @ 0x22ccc0
> Constructing Cat @ 0x22ccc0
> Copy Constructing Mammal @ 0xc306d8 from 0x22ccc0
> Caught a Mammal
> Destructing Mammal @ 0xc306d8
> Destructing Cat @ 0x22ccc0
> Destructing Mammal @ 0x22ccc0




Best

Kai-Uwe Bux
 
Reply With Quote
 
stevewilliams2004@comcast.net
Guest
Posts: n/a
 
      07-16-2007

> It would, yes, because the exception is then not caught and propagates
> out of "main".
>
> > in the catch
> > body, during the call to m.MyType().

>
> This I believe is a hypothesis of yours, and an incorrect one.


Nope - I verified this with a debugger. The MSDev debugger crashed on
the call m.MyType(), and in cygwin I got the cout just prior to the
call and not the one after it.

Also - looking with the MSDev debugger is shows that the VTable for
the m object is invalid (i.e. "Expression cannot be evaluated" or some
such method). The exception is *not* propagating out of main.

 
Reply With Quote
 
stevewilliams2004@comcast.net
Guest
Posts: n/a
 
      07-16-2007
On Jul 15, 8:20 pm, Kai-Uwe Bux <(E-Mail Removed)> wrote:
> (E-Mail Removed) wrote:
> > I was wondering if someone could explain the output I am getting for
> > the program below. What I expected from the main program output was
> > "Cat" but instead I see "Mammal". The output is also included below.
> > I got the same results with GCC 3.4.4 under cygwin as with MSDev
> > studio 2003. Even stranger to me, if I change the catch statement to
> > catch a Cat instead of a Mammal, the program crashes in the catch
> > body, during the call to m.MyType(). Thanks for any explanations in
> > advance.

>
> > Program:

>
> > #include <iostream>
> > using namespace std;

>
> > class Mammal
> > {
> > public:
> > Mammal()
> > {
> > cout << "Constructing Mammal @ " << this << endl;
> > }
> > Mammal(const Mammal& source)
> > {
> > cout << "Copy Constructing Mammal @ " << this << " from " <<
> > &source << endl;
> > }
> > ~Mammal()
> > {
> > cout << "Destructing Mammal @ " << this << endl;
> > }
> > virtual const char* MyType()
> > {
> > return "Mammal";
> > }
> > };
> > class Cat : public Mammal
> > {
> > public:
> > Cat()
> > {
> > cout << "Constructing Cat @ " << this << endl;
> > }
> > Cat(const Cat& source)
> > {
> > cout << "Copy Constructing Cat @ " << this << " from " <<
> > &source << endl;
> > }
> > ~Cat()
> > {
> > cout << "Destructing Cat @ " << this << endl;
> > }

>
> > virtual const char* MyType()
> > {
> > return "Cat";
> > }
> > };

>
> > int main(int argc, char *argv[])
> > {
> > Cat fluffy;
> > Mammal &fluffyRef = fluffy;
> > try
> > {
> > throw fluffyRef;

>
> You throw a Mamal. At this point, a temporary Mamal is created and
> initialized from fluffyRef, which involves slicing. See [15.1/3]:
>
> A throw-expression initializes a temporary object, called the exception
> object, the type of which is determined by removing any top-level
> cv-qualifiers from the static type of the operand of throw and adjusting
> the type from ?array of T? or ?function returning T? to ?pointer to T?
> or ?pointer to function returning T?, respectively.
>
> Note that the _static type_ is used for the temporary.
>
> Also note that a temporary copy is needed since the original is a local
> object that has to go down during stack unwinding.
>
> > }
> > catch (Mammal &m)

>
> At this point, the temporary implicitly created in the throw() is used to
> initialize the Mamal& here. Since slicing already happened, you don't get a
> Cat.
>
>
>
> > {
> > cout << "Caught a " << m.MyType() << endl;
> > return 0;
> > }
> > cout << "Nothing Caught" << endl;
> > return 0;
> > }

>
> > Output:

>
> > Steve@nessus /cygdrive/f/dev/src/TestWorkspace
> > $ ./TestWorkspace.exe
> > Constructing Mammal @ 0x22ccc0
> > Constructing Cat @ 0x22ccc0
> > Copy Constructing Mammal @ 0xc306d8 from 0x22ccc0
> > Caught a Mammal
> > Destructing Mammal @ 0xc306d8
> > Destructing Cat @ 0x22ccc0
> > Destructing Mammal @ 0x22ccc0

>
> Best
>
> Kai-Uwe Bux


Ok I think I am understanding now - and my last post was not entirely,
correct - I see now. Thanks for your quick responses.

 
Reply With Quote
 
Alf P. Steinbach
Guest
Posts: n/a
 
      07-16-2007
* (E-Mail Removed):
>> It would, yes, because the exception is then not caught and propagates
>> out of "main".
>>
>>> in the catch
>>> body, during the call to m.MyType().

>> This I believe is a hypothesis of yours, and an incorrect one.

>
> Nope - I verified this with a debugger. The MSDev debugger crashed on
> the call m.MyType(), and in cygwin I got the cout just prior to the
> call and not the one after it.
>
> Also - looking with the MSDev debugger is shows that the VTable for
> the m object is invalid (i.e. "Expression cannot be evaluated" or some
> such method). The exception is *not* propagating out of main.


Could theoreticalle happen because you have Undefined Behavior where
anything can happen (in principle), but my guess is you debugged
something that wasn't what you described.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
 
Reply With Quote
 
BobR
Guest
Posts: n/a
 
      07-16-2007

<(E-Mail Removed)> wrote in message...
> I was wondering if someone could explain the output I am getting for
> the program below. What I expected from the main program output was
> "Cat" but instead I see "Mammal". The output is also included below.
> I got the same results with GCC 3.4.4 under cygwin as with MSDev
> studio 2003. Even stranger to me, if I change the catch statement to
> catch a Cat instead of a Mammal, the program crashes in the catch
> body, during the call to m.MyType(). Thanks for any explanations in
> advance.
> Program:
>
> #include <iostream>
> using namespace std;


class Mammal{ public:
Mammal(){
cout<<"Constructing Mammal @ "<<this<<std::endl;
}
Mammal( Mammal const &source ){
cout<<"Copy Constructing Mammal @ "<<this
<<" from "<<&source<<std::endl;
}

// ~Mammal(){
// [Warning] class Mammal' has virtual functions but
// non-virtual destructor
// [Warning]`class Cat' has virtual functions but
// non-virtual destructor

virtual ~Mammal(){ // this quiets both warnings
cout<<"Destructing Mammal @ "<<this<<std::endl;
}
virtual const char* MyType(){
return "Mammal";
}
};
// no change to Cat
class Cat : public Mammal{ public:
Cat(){
cout<<"Constructing Cat @ "<<this<<std::endl;
}
Cat( Cat const &source ){
cout<<"Copy Constructing Cat @ "<<this
<<" from "<<&source<<std::endl;
}
~Cat(){
cout<<"Destructing Cat @ "<<this<<std::endl;
}
virtual const char* MyType(){
return "Cat";
}
};
>
> int main(int argc, char *argv[]){
> Cat fluffy;
> Mammal &fluffyRef = fluffy;
> try{


throw fluffyRef; // to get 'Mammal' (a sliced 'Cat')
// out: Copy Constructing Mammal @ 0xc5fb80
// from 0xacee04 (Cat fluffy)

// throw fluffy; // to get 'Cat'
// Copy Constructing Cat @ 0xc5fb80 from 0xacee04

> }

// add:
catch( Cat const &m ){
cout<<"Caught a "<<m.MyType()<<std::endl;
return EXIT_FAILURE;
}

> catch( Mammal &m ){
> cout << "Caught a " << m.MyType() << endl;
> return 0;
> }


// add:
catch( ... ){ // that's 3 dots (not a placeholder)
cout<<"Caught something, maybe the flu!"<<std::endl;
return EXIT_FAILURE;
}

> cout << "Nothing Caught" << endl;
> return 0;
> }


[ I'm not positive, this is my guess. ]
Your 'fluffyRef' is a ref to 'Mammal'. If you only caught 'Cat &c' (and not
'Mammal'), the program will exhibit an "un-caught exception" and terminate
which looks like a crash).

try{
throw fluffy;
}
// catch( Cat &m ){
// cout<<"Caught a "<<m.MyType()<<std::endl;
// }
catch( Mammal &m ){
cout<<"Caught a "<<m.MyType()<<std::endl;
Cat *cat = dynamic_cast<Cat*>( &m );
if( cat ){ cout<<"It's a Cat!!"<<std::endl;}
}
// out: Caught a Cat
// out: It's a Cat!!

throw fluffyRef;
// out: Caught a Mammal
// The cast fails, which I think is slicing the Cat (at throw).

--
Bob R
POVrookie


 
Reply With Quote
 
Guest
Posts: n/a
 
      07-16-2007
You can not expect polymorphism works in the try/catch idiom.
As the Holy Standard illustrates:

A throw-expression initializes a temporary object, called the
exception object, the type of which is determined by removing any top-
level cv-qualifiers from the static type of the operand of throw.[1]

For the solution of this problem, you can go to http://www.ddj.com/dept/cpp/184401940.



1.[1] ISO/IEC 14882:2003(E), "Programming Languages-C++," 15.1 63 and
"How do I throw polymorphically?" C++ FAQ Lite,
http://www.parashift.com/c++-faq-lit...html#faq-17.10.

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
JUnit 4.4 expected exception not working? dom.k.black@googlemail.com Java 6 03-25-2008 08:01 AM
HTML code not working as expected Dave Kelly HTML 3 12-25-2007 11:05 PM
Exception of type 'System.Web.HttpUnhandledException' wasthrown.Exception has been thrown by the target of an invocation.System.WebSystem.Exception jobs ASP .Net 1 11-16-2007 05:57 PM
while executing my client program i get the exception javax.naming.LinkException: [Root exception is javax.naming.LinkException: [Root exception is javax.naming.NameNotFoundException: remaining if plz anybody know how to solve this problem then mahesh Java 0 03-08-2007 12:26 PM
[suggestion] rubyunit - filename + exception expected Simon Strandgaard Ruby 0 06-27-2003 12:21 PM



Advertisments