Sign in to follow this  

[SOLVED] [C++] Exceptions - Catch clause for base class doesn't catch derived ...

This topic is 4338 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, I have an exception class hierarchy like this (simplified):
class ExceptionBase
{
protected:
    ExceptionBase( const ExceptionBase& rSource ) 
    { 
        // ...
    }

    ExceptionBase()
    {
        // ...
    }

public:
    virtual ~ExceptionBase()
    {
        // ...
    }

    virtual void raise() = 0;

};

class DerivedException : public ExceptionBase
{
public:
    DerivedException( const DerivedException& rSource ) : ExceptionBase( rSource ) 
    { 
        // ...
    }

    DerivedException()
    {
        // ...
    }

    virtual ~DerivedException()
    {
        // ...
    }

    virtual void raise()
    {
        throw *this;
    }
};


Now from all I know about exception handling, a catch clause for class ExceptionBase should also catch objects of class DerivedException, right? At least if I catch by reference, which I do. However, this is not what's happening in my program:
int func()
{
    try
    {
        DerivedException d;

        d.raise();
    }
    catch ( const ExceptionBase& rException )
    {
        std::cerr << "ExceptionBase caught" << std::endl;

        exit( 1 );
    }
    catch ( ... )
    {
        std::cerr << "Unkown exception caught!!" << std::endl;

        exit( 1 );
    }

    return 0;
}

int main()
{
    return func();
}

// Outputs: Unkown exception caught!!


Why?? =( I'm not getting it! I'm sure it's just stumbling over some stupid mistake again, but I just can't find it! [Edited by - Red Ant on January 26, 2006 8:27:44 AM]

Share this post


Link to post
Share on other sites
I'm not sure about, but: You're using a stack variable as an exception. At the moment of catching the scope of "try" is left, and hence the exception's object d is removed! I don't assume the compiler to have made a copy before, but perhaps I'm wrong.

I personally use only pointers to objects for catching exceptions (EDIT 2: but will no longer do so; see below). However, seen from the type system your solution should work, I think.


EDIT: gcc catches the exception regardless of whether its catch clause has a const qualified or a non-const qualified exception object specified.

Interestingly gcc also complains a private copy c'tor in the base class of exception, in the line of throw. So it seems that it actually does a copy!

[Edited by - haegarr on January 26, 2006 5:12:43 AM]

Share this post


Link to post
Share on other sites
I just compiled that code in MSVC 6.0 and it caught the ExceptionBase just as it should. What compiler are you using?

[edit] haegarr's point makes sense, I guess my compiler just optimized the code differently

Share this post


Link to post
Share on other sites
Works fine for me, using MinGW 3.4.4.
Which compiler did you use ?

Quote:
Original post by haegarr
I'm not sure about, but: You're using a stack variable as an exception. At the moment of catching the scope of "try" is left, and hence the exception's object d is removed! I don't assume the compiler to have made a copy before, but perhaps I'm wrong.


In function raise() the object is thrown by value:
"return *this;"
Catching by reference avoids unnecessary creation of copies.

Quote:

I personally use only pointers to objects for catching exceptions. However, seen from the type system your solution should work, I think. Or does also play the const keyword a role here?


Take a look at this page:
http://www.parashift.com/c++-faq-lite/exceptions.html
According to the FAQ, catching by pointers is not recommended.

Share this post


Link to post
Share on other sites
Quote:
Original post by haegarr
I'm not sure about, but: You're using a stack variable as an exception. At the moment of catching the scope of "try" is left, and hence the exception's object d is removed! I don't assume the compiler to have made a copy before, but perhaps I'm wrong.

I personally use only pointers to objects for catching exceptions. However, seen from the type system your solution should work, I think. Or does also play the const keyword a role here?


Catching exception by reference is the preferred way of doing it.

Share this post


Link to post
Share on other sites
I had a very similar problem to this a while back on an old compiler for VXWork (circa '95). If I remember correctly, I ended up having my base class inheriting from std::exception and this, for some odd reason, made my code behave as expected. I don't have any better explanation other than it just worked. Since we're not in VXWord anymore, I took it out again and have it like you do right now and it works in vs6, vs7.1 and gcc 3.2+(?) on both linux and windows.

Shadx

Share this post


Link to post
Share on other sites
Hello all,

I'm using the MSVC 7.1 compiler. The silly thing is, I recall this working correctly in an early test project I made a while ago, but now in my actual development project I get this funny behavior. I suppose I should make another test project and see what happens.

Share this post


Link to post
Share on other sites
I see from the site cited by nmi that pointers aren't good for exceptions due to memory handling. Although it isn't a problem in my software anyway, I accept that it is better to use references instead. So I have to do some more re-programming now :)

However, as already stated in an edit of my post above, it actually seems that a copy of the exception object is made, else the compiler wouldn't have to complain a private copy c'tor. So the question is left: what's wrong within the OP?

Share this post


Link to post
Share on other sites
Quote:
Original post by Shadx
I had a very similar problem to this a while back on an old compiler for VXWork (circa '95). If I remember correctly, I ended up having my base class inheriting from std::exception and this, for some odd reason, made my code behave as expected.


I omitted this detail for the sake of simplicity, but in fact my exception base is in turn derived from std::exception.

Share this post


Link to post
Share on other sites
Quote:
Original post by Red Ant
The silly thing is, I recall this working correctly in an early test project I made a while ago, but now in my actual development project I get this funny behavior.


So this code is part of your actual project ?
Since this code works fine the error must be in another part of your project.
Do you throw exceptions from destructors or something like that ?
Do you rethrow exceptions ?

Share this post


Link to post
Share on other sites
Nah, this isn't the actual code ... it's just a greatly simplified version of it. But I guess you're right, the mistake must be somewhere else because I just made a test project very much like the code I posted, but using my actual exception classes instead of the ones I made up here. And lo and behold ... it doesn't work!

I'm going to zip my test project and upload it so people can have a look at it.

http://www.geocities.com/red_ant_11/MyException_Test.zip

NOTE, this zip is stored on a Geocrappy account, which means simply clicking the link might not work. You may have to copy and paste the link.

Share this post


Link to post
Share on other sites
Right, I'm starting to go bonkers here. I've just compiled and run the original example WHICH APPARENTLY WORKS for you guys ... well, it doesn't for me. Unkown exception caught is what I get. It's driving me nuts. =(


P.S.

I've just used an older Visual Studio version (6.0) to compile and run first my original example and then my test project. Using 6.0, the original example works as expected, but my test project still gives me an "unkown exception caught".

[Edited by - Red Ant on January 26, 2006 7:36:13 AM]

Share this post


Link to post
Share on other sites
It sure does!!! =)))) Thanks a million, Shadx!! You have very likely kept me from going insane, hehe.

Well, this sure is a nastly little quirk. I think the Exception FAQ should totally emphasize this point!

Share this post


Link to post
Share on other sites

This topic is 4338 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this