Link to home
Start Free TrialLog in
Avatar of Lucsat
Lucsat

asked on

Throwing exceptions under Solaris

I have an exception class under NT inside a DLL. When I want to throw this exception, I use "throw new TException ("hello")".

Then I port this class to Solaris, but when the program flow gets to the catch statement, an "Abort" message appears and then the program stops. This doesn't happen under Windows NT : when a cpp throws the exception, the catch statement intercepts the exception and the program flow continues.

This is the code :

** In TException.so file :

class TException : public exception
{
public :
        TException (char *string);
        ~TException ();
}

** In TMyClass.so :

void TMyClass::f ()
{
       throw new TException ("hello");
}

** In main.cpp :

try {
    myclass->f ();
}
catch (TException *e) {
    printf ("catch...\n");

    delete e;
}

The message "catch..." doesn't appear. Appear an "Abort" message.

What's the matter?
Avatar of nietod
nietod

There's no way to tell from just that.  Could you show us some code?
Avatar of Lucsat

ASKER

Edited text of question.
Please do not edit the question once a dialog has started.  It makes it impossible for other experts to follow.

I don't see a problem there.  If you move the code to a single file does the problem go away?
Avatar of Lucsat

ASKER

Sorry for edit the question. I never use experts-exchange service and I'm a bit lost.

When I move all the code to a single file, then the problem disappears.

Another case : if main.cpp throws a TException exception, the catch statement works correctly.
>> Sorry for edit the question.
You shouldn't even be given the option to edit after a comment has been posted.  Hopefully that will be fixed in the next version.

That is sounding a lot like it has something to do with the implimentaiton of exceptions and DLLs on solaris.   (i.e it is not a C++ issue, but an OS-specific issue.)  There is a chance that you can get some more info here, but I sort-of doubt it.  Because this is so specific, I would consider gettting help from the compiler manufacturer or OS.  (maybe wait a little first to see what happens here.)  And there is a good chance that help might only be an explanation of why it doesn't work, not how to make it work.

Although I can't image why it wouldn't work...
Avatar of Lucsat

ASKER

Adjusted points to 50
Avatar of Lucsat

ASKER

I have found the problem :

When I declared the function that throws the exception, I use "MyClass::f () throws (TException)".

When I deleted the "throws (TException)" statement, then all was OK.

But, I don't understand why under Windows NT this statement functions but under Solaris or Linux doesn't works correctly.

What's the matter?
ASKER CERTIFIED SOLUTION
Avatar of nietod
nietod

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
>> When I declared the function that throws the
>> exception, I use "MyClass::f () throws (TException)".

This specificaton assures that the f() throws only TException (or types that convert to it) or doesn't throw at all.  If you attempt to throw any type that can't be converted to TException, the program won't allow it and will abort the program with an unhandled exception.

But you are throwing TException right?  wrong.  You are throwing "TException *".  This is a diferent type.  If you changed the throw code from

throw new TException ("hello");

to

throw TException ("hello");

Then you should be okay.

By the way, it is often best to throw exceptions by value, not pointer and is usually best to catch excetptions by reference, not value.

Let me know if you have any quesions.
Avatar of Lucsat

ASKER

Adjusted points to 60
Avatar of Lucsat

ASKER

There are only one problem : the locality of the throwed object.

When I use

throw TException ("hello")       (internally I store "hello")

in a function, this object only live in this function, and when an external function catch that exception, the "hello" string doesn't exist because in the TException destructor I use delete [] the_string.

Does TException store a pointer the string?  If so, did you write a working copy constructor (and while you are at it operator =) for the class.  The defaullt versions of these two procedures don't work right when you have data members that are to point to "private" blocks of allocated memory.  And the copy constructor will almost assuredly be used when throwing an exception.
Avatar of Lucsat

ASKER

The definition of TException are :

class TException
{
public:
   TException (char *pszString);
   ~TException ();

private:
   char *m_pszString;
};

TException::TException (char *pszString)
{
   m_pszString = new char (strlen (pszString) + 1);

   strcpy (m_pszString, pszString);
}

TException::~TException ()
{
   delete [] m_pszString;
}

I don't understand when you say me "write a working copy constructor". How I can to throw an exception using the copy constructor? How I can to change the char pointer to another solution (I'm sure that an static array is a solution, but I like to reserve memory as I need too much...)
If that is the entire class definition it definitely has a problem.   The problem has nothing to do with exceptions.  This is enherint in the current class design.  i.e. the class behaves poorly with or without an exception.  For example try

int main()
{
   TException A("this is a test.");

   {
      TException B(A);
   }
   return 0;
}

This should yeild an error at the end of main().  Actually this WILL yield  an error at the end of main, the only dobut I have is that your debugger might not pick it up.  try it.
The problem is that you have not provided a copy constructor so when TException object's are copied the default copy constructor is used.  This copy constructor does not work well for this case.  What it does is copy ever single member of the class.  So as a result the new TException object has the same pointer in m_pszString as the old.  i.e you have two objects that are both sharing the same string data.  when the first object is destroyed it deletes teh string and the 2nd object is left holding a pointer to string data that has been deleted.  

You need to write a copy constructor for this class that copies the string data.  Then it will be safe to make copies of TException.   (And the compiler makes copies when you throw--as well as other times.)

The same problem exists for operator =.  I you ever do an = with Texception you will have a problem too.  So you need to define you own operator = or make sure you never use operator = (declare it private for example) on this class.