try-catch dynamic memory cleanup
-
I am somewhat familiar with a try-catch block and that it automatically destructs objects on exception. However, I'm curious if it automatically frees dynamically allocated memory from the "new" operator?
void failfunc()
{
throw 1; // obviously not practical, just for example
}void main()
{
try
{
char *mystr = new char[512]; // something in the try block determines the size needed, so must be allocated in the try block
failfunc(); // would normally actually do something
delete [] mystr;
}
catch (int ierr)
{
//tell user an error occured
if (mystr != NULL) delete [] mystr; // is this line needed, or will the exception have freed mystr?
}
} -
I am somewhat familiar with a try-catch block and that it automatically destructs objects on exception. However, I'm curious if it automatically frees dynamically allocated memory from the "new" operator?
void failfunc()
{
throw 1; // obviously not practical, just for example
}void main()
{
try
{
char *mystr = new char[512]; // something in the try block determines the size needed, so must be allocated in the try block
failfunc(); // would normally actually do something
delete [] mystr;
}
catch (int ierr)
{
//tell user an error occured
if (mystr != NULL) delete [] mystr; // is this line needed, or will the exception have freed mystr?
}
}No, you have to free the memory yourself.
Cédric Moonen Software developer
Charting control [v1.4] OpenGL game tutorial in C++ -
I am somewhat familiar with a try-catch block and that it automatically destructs objects on exception. However, I'm curious if it automatically frees dynamically allocated memory from the "new" operator?
void failfunc()
{
throw 1; // obviously not practical, just for example
}void main()
{
try
{
char *mystr = new char[512]; // something in the try block determines the size needed, so must be allocated in the try block
failfunc(); // would normally actually do something
delete [] mystr;
}
catch (int ierr)
{
//tell user an error occured
if (mystr != NULL) delete [] mystr; // is this line needed, or will the exception have freed mystr?
}
}You have allocated memory in a heap by using new. And after that you are executing the next statement which is failing. As i Know you should delete the memory which is created dynamically. So in catch statement the deletion part is must. But if
failfunc(); // would normally actually do something
char *mystr = new char[512]; // something in the try block determines the size needed, so must
be allocated in the try block
Statement 1.....
delete [] mystr;then as function failed it will not try to execute the next statment so there it will skip the creation of memory .so you need not to delete ....
-
I am somewhat familiar with a try-catch block and that it automatically destructs objects on exception. However, I'm curious if it automatically frees dynamically allocated memory from the "new" operator?
void failfunc()
{
throw 1; // obviously not practical, just for example
}void main()
{
try
{
char *mystr = new char[512]; // something in the try block determines the size needed, so must be allocated in the try block
failfunc(); // would normally actually do something
delete [] mystr;
}
catch (int ierr)
{
//tell user an error occured
if (mystr != NULL) delete [] mystr; // is this line needed, or will the exception have freed mystr?
}
}Objects allocated on the heap (i.e. via
new
) are not freed automatically. Objects allocated on the stack (likeMyObject obj;
) are freed when they go out of scope (i.e. when the execution leaves the innermost {} that surrounds the declaration) or when an exception is thrown. So in your example, iffailfunc()
throws an exception other than an integer (which can easily happen when someone changes failfunc() but not main()), you got yourself a memory leak. However, you can use what's called a smart pointer to get the desired behavior. The smart pointer is is a helper class that is allocated on the stack and behaves like a regular pointer, and when an exception is thrown its destructor gets called. In that destructor, it calls delete[] on its pointee. Just google smart pointers. Example (not tested)://
// Smart pointer class for arrays
//
template< typename T >
class ArrayPtr
{public:
ArrayPtr( T\* pointee ) : \_pointee( pointee ) { } inline ~ArrayPtr() { if( \_pointee ) delete\[\] \_pointee; // Array destruction } operator T\*() { return \_pointee } // ... more needed here. Just google smart pointers. // Basically you need operator->, operator\*, but not operator& // plus assignment etc.
private:
T\* \_pointee;
};
//
// How to use it in your example
//
void failfunc()
{
throw 1; // obviously not practical, just for example
}void main()
{
try {
ArrayPtr< char > mystr( new char[512] ); // Freed automatically when mystr goes out of scope or an exception is thrown
failfunc();
} catch( int err ) {
// Tell the user something went wrong
std::cerr << "Error #" << err << std::endl;
}
}Or if you don't need to print out an error message:
template< typename T > class ArrayPtr { /*... see above*/ };
void failfunc() { /*... see above*/ }
void main()
{
ArrayPtr< char > mystr( new char[512] ); // Freed automatically when mystr goes out of scope or an exception is thrown
failfunc();
}Note that you cannot use the standard C++ std::auto_ptr for arrays since its destructor only calls
delete
, notdelete[]
. This also implies that you need a separate smart pointer type for data allocated withmalloc
since it must be freed usingfree
, notdelete[]
-
Objects allocated on the heap (i.e. via
new
) are not freed automatically. Objects allocated on the stack (likeMyObject obj;
) are freed when they go out of scope (i.e. when the execution leaves the innermost {} that surrounds the declaration) or when an exception is thrown. So in your example, iffailfunc()
throws an exception other than an integer (which can easily happen when someone changes failfunc() but not main()), you got yourself a memory leak. However, you can use what's called a smart pointer to get the desired behavior. The smart pointer is is a helper class that is allocated on the stack and behaves like a regular pointer, and when an exception is thrown its destructor gets called. In that destructor, it calls delete[] on its pointee. Just google smart pointers. Example (not tested)://
// Smart pointer class for arrays
//
template< typename T >
class ArrayPtr
{public:
ArrayPtr( T\* pointee ) : \_pointee( pointee ) { } inline ~ArrayPtr() { if( \_pointee ) delete\[\] \_pointee; // Array destruction } operator T\*() { return \_pointee } // ... more needed here. Just google smart pointers. // Basically you need operator->, operator\*, but not operator& // plus assignment etc.
private:
T\* \_pointee;
};
//
// How to use it in your example
//
void failfunc()
{
throw 1; // obviously not practical, just for example
}void main()
{
try {
ArrayPtr< char > mystr( new char[512] ); // Freed automatically when mystr goes out of scope or an exception is thrown
failfunc();
} catch( int err ) {
// Tell the user something went wrong
std::cerr << "Error #" << err << std::endl;
}
}Or if you don't need to print out an error message:
template< typename T > class ArrayPtr { /*... see above*/ };
void failfunc() { /*... see above*/ }
void main()
{
ArrayPtr< char > mystr( new char[512] ); // Freed automatically when mystr goes out of scope or an exception is thrown
failfunc();
}Note that you cannot use the standard C++ std::auto_ptr for arrays since its destructor only calls
delete
, notdelete[]
. This also implies that you need a separate smart pointer type for data allocated withmalloc
since it must be freed usingfree
, notdelete[]
-
Thanks very much for the descriptive information. The example code is an excellent solution for my problem. I really appreciate you taking the time to answer that thoroughly.
Glad I could help :)
-
I am somewhat familiar with a try-catch block and that it automatically destructs objects on exception. However, I'm curious if it automatically frees dynamically allocated memory from the "new" operator?
void failfunc()
{
throw 1; // obviously not practical, just for example
}void main()
{
try
{
char *mystr = new char[512]; // something in the try block determines the size needed, so must be allocated in the try block
failfunc(); // would normally actually do something
delete [] mystr;
}
catch (int ierr)
{
//tell user an error occured
if (mystr != NULL) delete [] mystr; // is this line needed, or will the exception have freed mystr?
}
}You could use something like Boost[^]'s scoped_array[^] to avoid having to free the memory using a
catch
.Steve