advice on try - throw - catch

G

Gus Gassmann

I have read a bit about exception handling, but I am still a bit
unsure of efficiency considerations and things like that. Here is the
situation:

string OSInstance::getInstanceName() {
try {
if (m_sInstanceName.length() <= 0) {
if (instanceHeader == NULL)
throw ErrorClass("instanceHeader object does not
exist");
m_sInstanceName = instanceHeader->Name;
}
return m_sInstance.Name;
}
catch(const ErrorClass& eclass) {
throw (ErrorClass eclass.errormsg);
}
}

Assume that instanceHeader is nonnull in 999,999 out of 1,000,000
cases, but in that last case it is really important to warn the user.
Is the above code efficient? Can the efficiency be improved? Also,
what happens after the method does catch the error and throws it
upstairs? Do I have to have another try-catch in the calling routine?
What if I don't? Would your approach be different in open source and
closed source code?

Thanks a million for any feedback.
 
J

John H.

if (m_sInstanceName.length() <= 0) {

From an efficiency perspective, m_sInstanceName.empty() is preferable
to m_sInstanceName.length()<=0.
m_sInstanceName = instanceHeader->Name;
}
return m_sInstance.Name;

At one point you mention a m_sInstanceName and at another point you
mention m_sInstance.Name. I can't tell from code not included, but
this may or may not be a typo.
what happens after the method does catch the error and throws it
upstairs? Do I have to have another try-catch in the calling routine?
What if I don't?

Throwing comes from the code that detected the problem. try/catching
is for the code that wants to know about (or deal with) the problem.
if (instanceHeader == NULL)
throw ErrorClass("instanceHeader object does not
exist");
m_sInstanceName = instanceHeader->Name;
}
return m_sInstance.Name;
}
catch(const ErrorClass& eclass) {

Here you throw and then catch right away. This isn't necessary,
because any code you execute when you caught could just be done
instead of throwing it to begin with.
catch(const ErrorClass& eclass) {
throw (ErrorClass eclass.errormsg);
}

When you caught the exception, you immediately threw it again without
taking any other action. This doesn't serve any purpose because the
behavior would have been the same if you hadn't caught it at all.
what happens after the method does catch the error and throws it
upstairs? Do I have to have another try-catch in the calling routine?
What if I don't?

Throwing an exception is a way to indicate to a function further up
the call stack ("upstairs") that a problem happened. When an
exception is thrown, it will work its way up the call stack until it
is caught. If works all the way up and exits main in this way, then
(depending on the compiler/OS), some message of varying detail may be
given to the user.
So if you want to handle the exception in some specific manner (which
is often the case), then yes, you will want a try/catch in the calling
routine (or the routine that called that routine, etc.)
Would your approach be different in open source and
closed source code?

No.

I will make up a little example that shows how exception might be used
in this scenario:

string OSInstance::getInstanceName() {
if (m_sInstanceName.length() <= 0) {
if (instanceHeader == NULL)
throw ErrorClass("instanceHeader object does not exist");
m_sInstanceName = instanceHeader->Name;
}
return m_sInstanceName;
}

void printName(OSInstance & os)
{
try
{
std::cout << os.getInstanceName();
}
catch(const ErrorClass& eclass)
{
std::cout << "Unable to print name (" << eclass.errormsg <<
")" << endl;
}
std::cout << "Have a nice day." << endl;
}

int main()
{
OSInstance os;
printName(os);
return 0;
}

Notice in this example, the function that throws the exception didn't
try to catch it. It was some upstream function that catches it. In
this case, it was printName. printName prints some error message and
then continues to run as normal (in this case,print have a nice day
and then return).

An alternative could have been:
void printName(OSInstance & os)
{
std::cout << os.getInstanceName();
std::cout << "Have a nice day." std::endl;
}

int main()
{
OSInstance os;
try
{
printName(os);
}
catch(const ErrorClass& eclass)
{
std::cout << "os failed to print name (" << eclass.errormsg <<
")" << endl;
}
return 0;
}

Here notice that if printName() runs and getInstanceName throw the
exception, the exception will go to printName, who doesn't catch it,
so the excpetion continues to main(). printName's "Have a nice day
message" will not get printed.

Yet another example:

void printName(OSInstance & os)
{
try
{
std::cout << os.getInstanceName();
}
catch(const ErrorClass& eclass)
{
std::cout << "Unable to print name (" << eclass.errormsg <<
")" << endl;
throw ErrorClass(string("Unable to print because ") +
eclass.errmsg);
}
std::cout << "Have a nice day." << endl;
}

int main()
{
OSInstance os;
try
{
printName(os);
}
catch(const ErrorClass& eclass)
{
std::cout << eclass.errormsg << endl;
os.instanceHeader = new InstanceHeader;
printName(os);
}
return 0;
}

Here printName catchs the exception, does some action, and then
rethrows the exception. main then catches it, and can do some more
actions.

A final example would be if neither main nor printName has a try/
catch. Then you would see some default platform specific behavior I
mentioned previously.

The examples are just for illustration, not saying they are reasonable
or correct.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top