Archived

This topic is now archived and is closed to further replies.

Exception class

This topic is 6277 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

i have created a simple exception class that stores a string with a description of an error. now, if i throw an instance of my class, i get an error and my app crashes. i read somewhere that exceptions are copied when they are thrown. so i thought the error would be that my string doesn't get copied properly, because it is a pointer. so i provided a copy constructor that copied the string. but now the weird part: the copy constructor gets never called, BUT it works! how can this be? i can even supply an empty copy constructor, and it will work thanks rid Edited by - Ridcully on 10/7/00 7:02:09 AM

Share this post


Link to post
Share on other sites
vc++ 6.0

here is my header code to show what i mean:

    
class CGenericException
{
public:
//EMPTY copy constructor. doesn''t get called, but if i remove it, the app crashes. if i declare it private i get a compile error.
CGenericException(CGenericException&){};

CGenericException(const char* error){m_strError = error;};
~CGenericException(){};
CGenericException(){};

void LogError();

protected:
virtual char* GetError();
const char* m_strError;
};

Share this post


Link to post
Share on other sites
yes, i have sp4 installed.
btw there was a typo in my code above. how i posted it, it will even work without the copy constructor.
the problem is when i remove the "const" from the "const char*" in the protected section, (which is then dynamically created) it crashes.

Share this post


Link to post
Share on other sites
You did not allocate space for the string!!..

Your second constructor should be

    

CGenericException(const char* error)
{
m_strError = new char[strlen(error)]; // allocate space for the string


// use strcpy to copy the string over

};


If you want to do the = like your code, then you need use a string object (like the STL string class) rather than a pointer.

Share this post


Link to post
Share on other sites
okay, i didn''t express me very clearly. what you see above is the working exception class. when i said "remove the const" i actually meant the "remove the const and allocate memory for the string and copy it"

here is the source that is not working, if i remove the empty copyconstructor

    
class CGenericException{
public:
//EMPTY copy constructor. doesn''t get called, but if i
//remove it, the app crashes. if i declare it private i get
// a compile error.

CGenericException(CGenericException&){};

CGenericException(char* error)
{
m_strError = new char[strlen(error)+1];
strcpy(m_strError, error);
};

protected:
char* m_strError;

};


rid

Share this post


Link to post
Share on other sites
You are probably facing the same problem I have.

I want to make sure the exception object is caught by reference only so I try to declare the copy constructor private. Guess what, it doesn''t compile because for some reasons, the compiler requires every thrown object to have a copy constructor (see error C4671)

In any case your, copy constructor is wrong. U shouldn''t leave an empty copy constructor even playing with pointers even though it isn''t called. Try this

CGenericException(const CGenericException& e)
{
if (m_strError)
delete[] m_strError; // need to free memory if it exists!

m_strError = new char[strlen(e.m_strError)];
strcpy(m_strError, e.m_strError);
};

I forgot to say this earlier, but you should set the string pointer to NULL in a default constructor

but what I suggest is to drop string pointers and use string objects directly. This is what I have. Almost the same, except I use string and inherit from the standard exception class

    
#pragma once

#include <exception>
#include <string>

namespace V
{
////////////////////////////////////


class BaseException : public exception
{
typedef std::string string;

public:

explicit BaseException(const string &s) : exception(""), str_(s) {};

virtual ~BaseException() {};

virtual const char* what() const { return str_.c_str(); }

protected:

string str_; // error string


}; // end class


////////////////////////////////////

} // end namespace

Share this post


Link to post
Share on other sites
Any object that is thrown as an exception must be copied, and hence have a public copy ctor, or one generated by the compiler.

Possibly the reason why your copy ctor was not getting called was because usually a copy constructor takes a const reference to the object type:

MyType::MyType(const MyType& copy);

And it is likely that the compiler was generating one for you and that is why it was blowing up - because the string was not being copied properly and it was deleted twice.

The reason why a copy must always be made is this: The object being will no longer be in scope once the exception is thrown.

Consider this:

    
// defined somewhere with proper copy semantics

class MyException;

void MyDumbFunction(void)
{
throw MyException( "Foolishness" );
}

// or...


void MyOtherDumbFunction(void)
{
MyException ex( "More Foolishness" );

throw ex;
}



In either of the above two cases the local variable, in the first example, a temporary, will no longer exist when the function exits ( normally or via the exception ), so the exception mechanism must always copy the object that is being thrown.

There is no way to enforce that an exception will be caught by reference. You just have to make sure to write your catch handlers correctly.



Edited by - SteveC on October 9, 2000 10:33:50 AM

Share this post


Link to post
Share on other sites