Advertisement

An exception queerness

Started by May 22, 2000 03:57 AM
1 comment, last by Void 24 years, 7 months ago
A bizzare exception encounter... I define an exception class that takes a string like so class Exception { char *error_string; Exception(char *string) // constructor { // allocate memory for error_string using new // strcpy it over } ~Exception() // destructor { // delete the memory allocated for the error_string } }; So I throw an exception of this class in some function (nested within other functions), the main try/catch block in the main program catches the exception and exits, like so void DummyFunction() { try { throw Exception("Test"); // throw the exception } catch(...) { throw; // rethrow the exception up to main } } The weird thing is, the destructor for the Exception class is called twice. And since the first instance will free the memory, the second call to the destructor cause an assertion failure in the C++ runtime lib of _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) When I set breakpoints, the error_string in the second call contains garbage, even though I set the pointer to NULL after freeing the memory. Is this how the exception class be written (using string pointers)? Or should I use a fixed size array.?? But even so, why are there two Exception objects? Shouldn''t the throw just ''throw'' the same object? Can anyone explain this??
I would have thought that throw() would just throw the same object, but it seems the copy constructor (which the compiler automatically adds in) is being called. Since you are just new()-ing the string memory when your exception class is constructed and delete()ing it on destruction, you would do better to use a fixed array.

The best solution in this case seems to be to store the const char* you hard-coded (without copying it) and that''ll last until after main() has returned. So although the pointer will be copied by an invisible copy constructor, the data will remain in memory until the program exits.

So it would be perfectly fine to write it this way:


class Exception
{
const char *error_string;

Exception(char *string) // constructor
: error_string(string) // just copy the pointer
{
}
};



I have to go now, so if anything wasn''t clear just post it and I''ll try to explain better.



- null_pointer
Sabre Multimedia
Advertisement
throw always creates a copy of the object to be thrown.
In fact it must, because the automatic variable that you are throwing is going out of scope.

e.g.

throw Exception( "error" );

the Exception class is created as a temporary variable and that is passed to the throw statement which then creates a copy to throw ( this is why you catch by reference )

When you do

throw;

You are rethrowing the current exception, and no copying occurs. That is why this is only valid within a catch block

Although just copying the pointer ( and not deleting it in the dtor ) will work in this example, if you want to use string variables you'll have a problem.

I'd recommend using std::string instead of char* inside the class and then just assign to the std::string class.

You can still have the ctor of the Exception class take in a char*.


Edited by - SteveC on May 22, 2000 10:22:01 AM

This topic is closed to new replies.

Advertisement