Link to home
Start Free TrialLog in
Avatar of ronan_40060
ronan_40060Flag for United States of America

asked on

Deallocating memory after throwing an exception

Currently the exception handling is done as shown in the following code snippete
tResult = CC_SJGetChargeDetail(hndlr,
                    p_ref_RefNum,
                   p_seq_SeqNum,
                 p_cod_ChargeType,
                &p_str_ErrorMsg,
               &p_str_prob_list,
                                          //&syslcProbList,
            p_txt_ApplErrorMsg,
            (unsigned char *)user_id,
            &p_cod_Error);

      // RPC Exception
      if (p_cod_Error !=  rpc_s_ok)
      {
                  TRACE("DCE/RPC Error status =" << p_cod_Error <<"++++++");
                  TrimsCustomException * exc = new TrimsCustomException();
                  exc->msgId="SSCDCEEXP003";
                  exc->msgText="RPC Exception";
                  arm_stop(cas_start_handle,ARM_ABORT, 0, 0, 0);
                  free(user_id);
                  user_id = NULL;
                  throw exc;
      }

p_cod_Error is the OUT parameter from RPC CC_SJGetChargeDetail.
In the condition if (p_cod_Error !=  rpc_s_ok)
throw exe;
the object doesnt get distroyed and deallocated , how can it be deallocated otherwise the memory will get accumulated and eventually caused core dump.
Can delete exe; be used after  throw exe;  ?


Thanks
Ronan
Avatar of evilrix
evilrix
Flag of United Kingdom of Great Britain and Northern Ireland image

You should never throw exception objects that have been allocated from the heap for exactly the reason you have identified. Exception objects should always be stack based and thrown by copy. So, in your code you should do this...


TrimsCustomException exc();
exc.msgId="SSCDCEEXP003";
exc.msgText="RPC Exception";
throw exc;

If the TrimsCustomException object is not copy safe it is not a suitable candidate for an exception object. You should consider using the standard C++ exception object, std::runtime_error.





Also, when you catch exceptions always catch them by reference to the base exception class and prefer const reference. This will ensure that if the class is polymorphic you'll get correct polymorphic behavior. If you look at the exception hierarchy for standard C++ exceptions you'll see they are all based upon std::exception so this is all you need to catch. Example below


#include <stdexcept>
#include <iostream>
try
{
     throw std::runtime_error("it went wrong");
}
catch(std::exception const & ex) // Ensure I get polymorphic behavior.
{
    std::cerr << ex.what() << std::endl;
}

Open in new window

Avatar of ronan_40060

ASKER

Evilrix
Thanks for your reply
I will implement the 1st suggestion you mentioned and will let you know
Sure thing. Please feel free to ask for more clarification if you need it. Exception handling can, initially, be a little confusion -- but once you understand the mechanism it is a very powerful tool.

Good luck my friend.

-Rx.
Just one other thing. Another reason it's good to use the standard exception class is that your catch handlers can be simpler. If you write your own class and it is not based upon std::exception you'll need to have 2 handlers, one for your class and one for std::exception since any C++ code can throw std::exception so you should always look to handle this can so as to ensure your code is exception safe. It's simpler to base your class on std::exception and then that is all you need to catch.

Example below...


#include <iostream>
#include <stdexcept>
 
// Custom exception class, based upon standard exceptions
class TrimsCustomException :: public std::runtime_error // runtime_error is a type of std::exception
{
     TrimsCustomException(char const & msg) : std::runtime_error(msg){}
}
 
try
{
     throw TrimsCustomException("it went wrong");
}
catch(std::exception const & ex) // Will catch all standard exceptions AND TrimsCustomException
{
    std::cerr << ex.what() << std::endl;
}

Open in new window

Oops, type: TrimsCustomException(char const & msg) : std::runtime_error(msg){}

Should have been: TrimsCustomException(char const * msg) : std::runtime_error(msg){}

:)
I come from scripting languages, so I don't like to take care of the pointers so mutch. Smart pointers do the work in a clean way and the are not so slow.

Advantages:
Don't care with Exception
Don't care with Destructores most of the time
Less time to market, since I will have less problems
...

Desadvantage,
a little bit more memory involved and some CPU cycles  

Look to: http://ootips.org/yonat/4dev/smart-pointers.html
I agree smart pointers and the RAII idiom in general are a must in C++ programming, however this specific Q is related to mistakingly using heap allocated memory to throw exceptions. The use of smart pointers does not change this fact.

http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization

I'd suggest the boost::shared_ptr range of smart pointers are the criterion for which others should be compared.

http://www.boost.org/libs/smart_ptr/shared_ptr.htm
Also, as long as you observe the fact that it has move rather than copy semantics the Standard C++ std::auto_ptr is a perfectly acceptable smart pointer.

http://en.wikipedia.org/wiki/Auto_ptr
http://www.cppreference.com/cppmisc/auto_ptr.html
http://www.gotw.ca/publications/using_auto_ptr_effectively.htm

More useful information on exceptions
http://www.parashift.com/c++-faq-lite/exceptions.html
I'm sory, You wont to have a object in the stack being copied.

I don't now the size of the object, but a smart point has 4 bytes, so I'm coping 4 bytes in each level.

The other solution seems to have at least 2 string. They will be longer the 4 bytes for sure, so you are copying more data around.

I really don't like the auto_ptr, the reference count is a very useful feature. Not existing, seems to me that you lose the biggest advantage of the smart pointers.
Maybe I did a big mistake.

This is RPC, so the exception is supposed to pass in the Internet, correct?

So I rest my case, set you stuff in the stack an copy it.
@olerber, the correct semantics for throwing an exception in C++ is by value and NOT by smart pointer. There is a very good reason for this! If you throw by smart pointer you CANNOT catch exceptions by the base class. The smart pointer will have a specific signature, which will be different for each instance of it!

smart_ptr<std::excecption> and smart_ptr<std::runtime_error> have no class hierachy relationship, therefore you would need to catch both explicitly. Then, what about all other exceptions? You'd need a lot of exception handlers.

The cost of throwing an exception is always expensive, no matter what object your throw. An exception should only be thrown as a last resort when no other action can be taken to remidy the problem. You should also note that there is only one instance ever created on the stack, the compiler will optimize away all other copies (if any) created during stack unwinding. The important thing, as I've alreasy stated, is to catch by a reference to the exception base class.

I hope this helps clarify.

-Rx.
>> The smart pointer will have a specific signature, which will be different for each instance of it!
To demonstrate the problem, try compiling the code below.
#include <memory> 
#include <stdexcept>
int main()
{
	std::auto_ptr<std::runtime_error> r;
	std::auto_ptr<std::exception> const & e = r;
 
	return 0;
}

Open in new window

Hi ronan_40060,

Do you need anymore assistance with this?
Evilrix and Oleber
Thanks for all your valuable comments
Im going to use the following
TrimsCustomException exc();
exc.msgId="SSCDCEEXP003";
exc.msgText="RPC Exception";
throw exc;
I did try Try and catch with its clashing with the Systinet C++ Server that we are using to deply the SOAP Based Server for which this exception handling code is being written.

Here above since no object is created , deallocating wont come into picture.
I will let you know
Thank you guys
I will close this question very soon
Thanks
Ronan
ASKER CERTIFIED SOLUTION
Avatar of evilrix
evilrix
Flag of United Kingdom of Great Britain and Northern Ireland image

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
Im getting the following errors
Error 583: "wfmclifService.cpp", line 53 # Left side of '.' requires a class object; type found was a function 'TrimsCustomException ()'. Did you try to declare an object with
    a nested constructor call? Such a declaration is interpreted as a function declaration "TrimsCustomException exc()" ["wfmclifService.cpp", line 52].
                            exc.msgId="SSCDCEEXP003";
                            ^^^                      
Did you read my post above? http:#20813041

TrimsCustomException exc() does not create an object, it creates a temporary that only exists for the duration of that one line. Try TrimsCustomException exc;
Sorry Evilrix
I read your comment after I posted my comment , sorry for that
I have done the following
TrimsCustomException exc;
exc.msgId="SSCDCEEXP003";
exc.msgText="RPC Exception";
throw exe;
and it doesnt throw any errors
But could you please let me know more how memory will be used in this case.
One instance of TrimsCustomException will be created and this will be propagated back down the call stack during stack unwinding to the point where it is caught (assuming it is caught). There should be no greater cost than throwing heap allocated object. Bearing in mind that throwing an exception is always an expensive task and the fact that you are throwing one must indicate an error so the cost of throwing the object is probably the least of your worries :)

This is the standard way to throw an exception in C++, it is the correct idiom to use.
Excellent