Sunday, January 09, 2005

Exceptions creating Exceptional Problems!

Hello,

Exception handling is cool, but can be a pain in the... donkey sometimes!
LinSock++ is just inches away from being finished, what remains is just error handling. This is what troubling us from past 5 days...


//Socket class

class Socket
{
Socket()
{
if(error_on_doing_something())
{
throw SockException("ErrMessage", code);
}
}

do_something_else()
{
if(error_on_doing_something())
{
throw SockException("ErrMessage", code);
}
}
};



//Main program

#include<...>
void main()
{
try
{
Socket object();
object.do_something_else();
}catch(SockException err)
{
err.getCode(); //works
err.getMessage(); //works
//object.cannot_access_this(); <----- this is troublesome!
}
}


Now consider this,
If i create a TCP socket, which fails to connect, the user might want to connect after a timeout in the catch block, or call a function from there to do it. But when control reaches the catch block, the "object" is either destroyed or yet not created (behaviour of C++ exceptions) & hence the user is stuck!

In a nutshell, accessing the object in which exception occured is not being possible in catch block.

How to overcome this problem?
Any other solutions... workarounds...

All comments/flames/suggestions are welcome.

cya,
makuchaku

4 comments:

makuchaku said...

One possible solution found as suggested by Anduin on #C++ [at] irc.freenode.net

int main()
{
Socket s;
try
{
s = new Socket(ERRORNEOUS_VALUE);
}catch(...)
{
s->memberFunction();
}
}

Atleast this compiles! :-D

makuchaku said...

oops!
Socket *s

:-D

Anonymous said...

Hi there,
A constructor/destructor should never throw an exception.
What are you going to delete when the constructor throws? If you are creating an array of sockets and one of the constructors throws, which objects have to be deleted?

Anonymous said...

Comment on what the other anon said.
Constructors are allowed to throw and sometimes should but destructors should never throw.

But in this case the throw in the constructor conflicts with what you want to do with the class, so remove it.
Then you get something like:
class Socket
{
public:
Socket(): initialized(false) {}
Init()
{
if(error_on_doing_something())
{
throw SockException("ErrMessage", code);
}
}

do_something_else()
{
if(!Initialized)
{
Init();
}
if(error_on_doing_something())
{
throw SockException("ErrMessage", code);
}
}
private:
bool Initialized;
};