Click to See Complete Forum and Search --> : allocating memory with new


Brendan Cullen
May 14th, 1999, 05:49 AM
Hi,

Is there any circumstance in which it is okay not to check for success after a "new" ? I am seeing a lot of code that attempts to create objects on the heap using new without there being a check.

classx * myptr = new classx;
if (myptr==NULL) // this is missing.......
{
}
else // I succeeded
{
etc
etc
}

Jason Teagle
May 14th, 1999, 06:31 AM
I guess most people assume that under normal circumstances, the 'new' would not fail - because of large memory in PCs and virtual memory, etc. If, however, you are using (allocating) a lot of memory, or creating a large number of large objects, then checking the return value is the good thing to do. There is no harm in it, it is good practice.

Many people often don't check pointers obtained from functions, either - they assume that it will work because they expect everything to be running normally on their system - they expect their code to behave and produce the right results. That is one area, however, where I disagree - I check pointers form functions rigourously; there is a far higher risk of one of these being NULL than a 'new' failing.

Any comments?

Todd Jeffreys
May 14th, 1999, 06:31 AM
That is excellent practice. Ideally you should always check if new fails. But %99.999999 it works, so sometimes we programmers leave it out.

Brendan Cullen
May 14th, 1999, 06:57 AM
I too check the results of new and the value of pointers returned by functions.

Thanks,

Brendan

Brendan Cullen
May 14th, 1999, 06:58 AM
Thanks Todd,

Brendan

PChetan
May 14th, 1999, 11:06 AM
Hello,

According to me the good programming style is that create a small template class which will simulate the idea of smart pointers.
Use this template class to declare a pointer to any object and then allocate memory for this pointer.
The constructor of this class will check for the success. If failed, will throw an exception.
You use SEH in your program so that if smart pointer throws an exception your program can catch and process it.

What I am trying to say is

try
{
smart_ptr<any Object type> *Ptr = new (...)
....
....
}
catch(...)
{
exceptions are handled here.
}

At least this is the normal practice I use to follow in all my projects.

Any comments?

Thanks
Chetan



Nothing is impossible.

May 14th, 1999, 11:10 AM
If you are using exceptions in C++, one is thrown in the event that new fails. So, instead of doing this sort of checking all over the place, you can catch the allocation failure.

It makes the code much cleaner to read.

Jason Teagle
May 17th, 1999, 02:29 AM
An interesting way of doing it, but doesn't it require more code to handle it? I.e. (I have never used template programming before (never found a need), so if the syntax is wrong, I apologise),

---

BOOL bFailed = FALSE ;
CMyObject *pMyObj ;

try
{
pMyObj = smart_ptr<CMyObject>
}
catch(...)
{
bFailed = TRUE ;
}
end_catch

if (!bFailed)
{
// Rest of code here...
}



---

versus:

---

CMyObject *pMyObj ;

pMyObj = new CMyObj ;
if (pMyObj != NULL)
{
// Rest of code here...
}



---

... or have I got the use of your smart pointer wrong?

Jason Teagle
May 17th, 1999, 02:38 AM
I'm not sure I agree; I feel

---

CMyObject *pMyObj ;

pMyObj = new CMyObject ;
if (pMyObj != NULL)
{
}



---

is neater and easier to follow than

---

CMyObject *pMyObj ;

try
{
pMyObj = new CMyObject ;
}
catch(...)
{
}
end_catch



---

This is especially true if you have to allocate several objects at the start of a program, where later objects rely on the pointers allocated earlier; trying to prevent later objects from being created if one of the dependent pointers fails with try-catch blocks becomes more awkward, since they encapsulate the failed condition (where you want things to stop) rather than the successful condition (where you want things to continue).

I realise that you could issue a return command at the point of failure, but for the scenario above this would result in several returns within the same function - I was taught to have only one exit point in a routine, so this is a no-no for me.

sally
May 17th, 1999, 03:51 AM
I disagree with you...

I find this harder to read:


CMyObject *pMyObj;
pMyObj = new CMyObject;
if (pMyObj != NULL)
{
// report error
}

CMyObject *pMyObj2;
pMyObj2 = new CMyObject;
if (pMyObj2 != NULL)
{
// report error
}

CMyObject *pMyObj3;
pMyObj3 = new CMyObject;
if (pMyObj3 != NULL)
{
// report error
}

CMyObject *pMyObj4;
pMyObj4 = new CMyObject;
if (pMyObj4 != NULL)
{
// report error
}

CMyObject *pMyObj5;
pMyObj5 = new CMyObject;
if (pMyObj5 != NULL)
{
// report error
}




than this code:


CMyObject *pMyObj;
CMyObject *pMyObj2;
CMyObject *pMyObj3;
CMyObject *pMyObj4;
CMyObject *pMyObj5;
try
{
pMyObj = new CMyObject;
pMyObj2 = new CMyObject;
pMyObj3 = new CMyObject;
pMyObj4 = new CMyObject;
pMyObj5 = new CMyObject;
}
catch(...)
{
// report error
}
end_catch




I find that using exceptions stops me from from having to return error codes through out the system
When a problem occurs, an exception is raised and I can respond to it in a clean and object oriented way

Sally

Sally
May 17th, 1999, 03:51 AM
I disagree with you...

I find this harder to read:


CMyObject *pMyObj;
pMyObj = new CMyObject;
if (pMyObj != NULL)
{
// report error
}

CMyObject *pMyObj2;
pMyObj2 = new CMyObject;
if (pMyObj2 != NULL)
{
// report error
}

CMyObject *pMyObj3;
pMyObj3 = new CMyObject;
if (pMyObj3 != NULL)
{
// report error
}

CMyObject *pMyObj4;
pMyObj4 = new CMyObject;
if (pMyObj4 != NULL)
{
// report error
}

CMyObject *pMyObj5;
pMyObj5 = new CMyObject;
if (pMyObj5 != NULL)
{
// report error
}




than this code:


CMyObject *pMyObj;
CMyObject *pMyObj2;
CMyObject *pMyObj3;
CMyObject *pMyObj4;
CMyObject *pMyObj5;
try
{
pMyObj = new CMyObject;
pMyObj2 = new CMyObject;
pMyObj3 = new CMyObject;
pMyObj4 = new CMyObject;
pMyObj5 = new CMyObject;
}
catch(...)
{
// report error
}
end_catch




I find that using exceptions stops me from from having to return error codes through out the system
When a problem occurs, an exception is raised and I can respond to it in a clean and object oriented way

Sally

Jason Teagle
May 17th, 1999, 04:09 AM
With the example you have given, I agree; the one catch for all errors is neater and more compact.

However, as I have mentioned in another response, if some later objects require pointers allocated before, and you don't want them created if the dependencies fail, the try-catch becomes more unwieldy.

Thanks for everyone's input.

Dave Lorde
May 17th, 1999, 04:37 AM
The principle behind the try...catch is that you can write the body code of your function without worrying about failures, i.e. as if you assume everything will succeed, then you can catch any exceptions at the end. There is rarely a need for additional checks using a boolean 'failed' flag.

I would code your example something like this:

try {
smart_ptr<CMyObject> spMyObj(new CMyObject());
// Continue body of function here...
}
// End of function tidy up
catch(smart_ptr_exception& spe)
{
// handle exeption
}
catch(...)
{
// exceptions from rest of code
}

[The smart_ptr syntax depends on the smart_ptr and what you want to do with it]

In fact, in standard C++, it is the 'new' that throws the exception in this situation.

If circumstances lead to more than one 'try' block in a function, I usually take it as an indication that it should be split up into further functions.

Dave

sally
May 17th, 1999, 04:44 AM
In that case I'd do this...


CMyObject *pMyObj1 = NULL;
CMyObject *pMyObj2 = NULL;
CMyObject *pMyObj3 = NULL;
CMyObject *pMyObj4 = NULL;
CMyObject *pMyObj5 = NULL;
try
{
pMyObj1 = new CMyObject;
pMyObj2 = new CMyObject;
pMyObj3 = new CMyObject;
pMyObj4 = new CMyObject;
pMyObj5 = new CMyObject;
}
catch(...)
{
// report error
delete pMyObj1;
delete pMyObj2;
delete pMyObj3
delete pMyObj4
delete pMyObj5
}
end_catch

Sally
May 17th, 1999, 04:44 AM
In that case I'd do this...


CMyObject *pMyObj1 = NULL;
CMyObject *pMyObj2 = NULL;
CMyObject *pMyObj3 = NULL;
CMyObject *pMyObj4 = NULL;
CMyObject *pMyObj5 = NULL;
try
{
pMyObj1 = new CMyObject;
pMyObj2 = new CMyObject;
pMyObj3 = new CMyObject;
pMyObj4 = new CMyObject;
pMyObj5 = new CMyObject;
}
catch(...)
{
// report error
delete pMyObj1;
delete pMyObj2;
delete pMyObj3
delete pMyObj4
delete pMyObj5
}
end_catch

sally
May 17th, 1999, 04:45 AM
I'd also put a ; last on the last 3 delete statements

Sally

Sally
May 17th, 1999, 04:45 AM
I'd also put a ; last on the last 3 delete statements

Sally

Daren Chandisingh
May 17th, 1999, 09:46 AM
I think that the throwing of an exception depends upon which new is called. CObject:: operator new thows an exception but I don't think template<class T> void *operator new does. E&OE, of course.

--
Daren Chandisingh