As title says, i know that new throws an exception which can be caught, but what exactly happens to the pointer? it turns NULL? I checked some answers on SO but none explain
If an exception is thrown, then the pointer will not be assigned a new value. If your pointer is scoped inside of the try
block where you do the allocation, or is not scoped in any try
block, then the exception will cause the scope to change such that you can't access the pointer any more. Consequently, there's no need to test the pointer.
If, on the other hand, the pointer is declared in a way where it persists after the allocation fails, then you would need to check the value. For example:
T* ptr = NULL;
try {
ptr = new T();
} catch (std::bad_alloc& ) {
/* ... handle error */
}
// Have to test ptr here, since it could still be NULL.
Hope this helps!
When an exception is thrown out of a function the function does not complete and does not return anything, at the same time control flow jumps to the exception handler and even if the function returned, the assignment to the receiving pointer would not be executed.
The same goes for the throwing version of new
, if it throws, then the pointer would maintain the same value it had before the expression, which might be NULL or any other value.
On the other hand, if you use new (std::nothrow) X;
then the call to new
will not throw, and failure will be indicated by a NULL value being returned (and assumingly assigned to a pointer)
Assuming you are using the default global new
operator, and have not used the nothrow
version of new
:
int main( int argc, char *argv[] )
{
//if new fails, what 'pFile' turns out to be? and do I need to delete
//it later?
CFileStatic *pFile = new CFileStatic( "Console.h", READ_WRITE );
/* ... */
}
There is no "later". In this code, if new
fails, it will throw an std::bad_alloc
exception, and your program will terminate immediately.
Now, if you were to try to handle this situation, you would need to catch that exception. Perhaps like this:
int main( int argc, char *argv[] )
{
//if new fails, what 'pFile' turns out to be? and do I need to delete
//it later?
try
{
CFileStatic *pFile = new CFileStatic( "Console.h", READ_WRITE );
}
catch( const std::bad_alloc& ex )
{
cout << "whoops! out of memory." << ex.what() << endl;
}
/* ... */
}
pFile
exists within the scope enclosed by the try
block, so it no longer exists. Moving out one level:
CFileStatic * pFile = 0;
try
{
pFile = new CFileStatic( "Console.h", READ_WRITE );
}
catch( const std::bad_alloc& ex )
{
cout << "whoops! out of memory." << ex.what() << endl;
}
// pFile is still 0
pFile
is never modified, so the value is unchanged.
Regarding the question of delete
ing the pointer. The Standard says (C++03 5.3.5/2):
[...] if the value of the operand of delete is the null pointer the operation has no effect.
You do not have to delete a NULL pointer, because there is nothing to delete
, but doing so will have no effect. You could safely do this:
CFileStatic * pFile = 0;
try
{
pFile = new CFileStatic( "Console.h", READ_WRITE );
}
catch( const std::bad_alloc& ex )
{
cout << "whoops! out of memory." << ex.what() << endl;
}
delete pFile; // regardless of the success of new, this is OK
Note that when doing this, it is especially important that you initialize pFile
to the null pointer, as I've done here. If you don't:
CFileStatic* pFile; // NO INIT
/* ... */
delete pFile; // if new threw, this is undefined behavior
pFile
will still be a garbage pointer. It's not the null pointer, so delete
will try to delete it, resulting in Undefined Behavior.
If new
fails it throws a std::bad_alloc
exception, unless you use the nothrow
version. This means that the value of the variable to store the returned pointer will be unchanged.
If you catch the exception the value of pFile
remains uninitialized, otherwise your application terminates (as main
is exited)