Advertisement

try catch & cleaning up

Started by July 27, 2000 12:24 AM
6 comments, last by baskuenen 24 years, 4 months ago
Is it wise to use try/catch in C++, regarding memory? For example:
    
void proc()
{
  myclass *pobject = new myclass(...);
  myclass object;

  ...call another proc, and do some more stuff...
  ...somewhere an error occurs...

  delete pobject;
}

main()
{
  try
  {
    proc();
  }
  catch(...)
  {
     cout << "Our mem is now fucked up..." << endl;
  }
}
    
If I run above program, "pobject" is not freed. Is it? If it would be allocated on the stack like "object", the mem would be freed - so is it better to use stack allocated instead of heap allocated objects? If I would create a lot of stack allocated objects, and then an exception occurs...will any destructors be called? If not - all other objects that that class would have created are still in mem... If they are called, and another exception occurs, what does happen then? Is the solution to use tons of try/catch statements, in every function? Is try/catch fucking up memory? Please prove me wrong...
One possible solution is to override the global new/delete operators and have them build a linked list of all the memory you allocated, then remove the nodes when you delete them. When your program catches a fatal exception, go through the linked list and free all the memory before quitting. (Hey, it''s automatic garbage collection!)

This is kind of brute force and really slows down delete so if you''re doing a lot of memory work in a time-critical area (which you shouldn''t be) then it might not be the best solution.
I think try/catch are best used in a completely OOP enviornment where the destructors will automatically clean up everything. (Well, not everything, but the leaked memory will usually be very negligent, if anything.) Also you shouldn''t use try/catch for trivial and recoverable errors, only fatal earth-shattering cataclysmic we''re all gonna die! kind of errors.

-RWarden (roberte@maui.net)
Advertisement
If you want to use exceptions, then you have to make everything stack based so the dtor can be called automatically when it goes out of scope (either through normal termination or exception occurring)..

If you need to "new" stuff, try looking at auto_ptr in the STL..It wraps the heap object into a stack object so it will be auto deallocated no matter what happens (ie all stack objects will have their destructor called).

When an exception occurs, it acts like a return statement so it''s not possible (??) to throw another exception.. unless the dtor can throw exceptions (which is dtor is not recommended to do)
RWarden:
Overriding the global new/delete operators and have them build a linked list, good solution!
But I would have to write lots of code for this, and include it in my program. I found the try/catch stuff so good for it''s easy (little code) error handling.
You''re also saying I should only use try/catch for "we''re all gonna die!" kind of errors. I beginning to agree with you on this one. Shame it aint more...

Void:
Good point on dtor not throwing exceptions! I almost forgot


So, to be sure: is this the way to use new/delete in combination with try/catch:
    void main(){  CObject *pObject = NULL;  try  {    pObject = new CObject(...);    ...do something...  }  catch(...)  {  }  if (pObject)  {    delete pObject;  }}    


Things that come to mind:
  • I must use = NULL, else I can''t check if(pObject) in the end.
  • I must check for if(pObject) in the end because an exception could be thrown from the constructor. (object would never be allocated). If I don''t delete will give an error.



  • This code seems like overdoing it - doesn''t it?
    If I would use this consistantly, I would ALWAYS have to check if an object still exists before I delete it....
    I only saw this kind of code at school...(this probably says enough )

    You could try the following - lets the exception propagate also, which is usually a good thing otherwise you wont know why the function failed:


    void func()
    {
    std::auto_ptr objAutoPtr( new CObject );
    objAutoPtr->DoSomething();
    }


    How do you get the source code listing view to work?
    I forgot.

    Edited by - SteveC on July 27, 2000 11:21:31 AM

    Edited by - SteveC on July 27, 2000 11:22:41 AM

    Edited by - SteveC on July 27, 2000 11:23:21 AM
    You can also "rethrow" the exception upwards in the catch handler to propagate the exception upwards, but the autoptr method is cleaner..
    Advertisement
    quote:
    I must check for if(pObject) in the end because an exception could be thrown from the constructor. (object would never be allocated). If I don''t delete will give an error.


    You don''t need the check, calling delete on a null pointer has no effect so you wont get an error, it''ll also make you code easier to read cos you don''t have lots of ''noise'' in the way (e.g. if(pObject)).

    new and delete don''t mix well with exceptions, you use a class that can allocate the memory in it''s ctor and free it in the dtor (dtors are called for all local objects when the stack is unwound. The standard auto_ptr class is a good example of this (but don''t try to store them a container), you can use it like this (you''ll might need to edit this message to see the code properly):

        #include <memory> //std::autp_ptr is in hereint main(){	try	{		std::auto_ptr<CObject> pObject(new CObject);		//use pObject like a normal pointer, but dont delete it. it''ll be deleted for you		//do somthing...	}	catch(...)	{	}		return 0;}    


    If this function wasn''t main, you would also be able to miss out the try & catch since it doesn''t matter if an exception happens, all your objects will be safely destroyed.
    Thanks people, I learned a lot here

    Especially the auto_ptr template was new for me. Cool stuff that auto_ptr - simple but effective. This is really where the power of C++ kicks in

    This topic is closed to new replies.

    Advertisement