struct node {
node() {
cout<<"constructor \n";
}
int i ;
} ;
template<class T> T* myNew(T a) {
T *retVal = new T;
if (retVal == NULL) {
cout<<"error : cannot allocate memory \n";
exit(-1);
}
return retVal ;
}
int main() {
node Obj;
node *p = myNew(Obj) ; // this is line 31 in my file
return 0;
}
Now, my questions are
1. I am not sure if this is right?
2. if it is right, then I don't want to create this unnecessary Obj which I created just to send argument to myNew because if I don't do it this way, I get this compilation error
myNew.cc: In function ‘int main(int, char**)’:
myNew.cc:31: error: expected primary-expression before ‘)’ token
1) new will never return a null pointer. If allocation failes, it throws an exception. You can MAKE it return null instead of throwing by using the nothrow parameter, but it doesn't do that by default.
1 2 3 4 5 6 7 8 9 10 11 12 13
try
{
int* a = newint;
// code reaches here only if 'a' was allocated successfully
int* b = new(std::nothrow) int;
// code can reach here even if 'b's allocation failed.
if(b == 0) { /* b allocation failed */ }
}
catch(std::bad_alloc& err) // or catch(...) if you're lazy or want to catch all exceptions
{
// a alloctaion failed
}
If you're really lazy you can leave out the try/catch blocks completely. The exception will still be thrown, and if you never catch it anywhere it will just crash your program.
Exceptions provide lots of benefits over the normal C-style "check for error conditions after every line" approach. But that's another tale.
2) If you want to change new's behavior, you're better off overloading new rather than making a new function. You can create your own behavior for new and delete. See the reference page on new:
3) constructos can't return values, so your approach wouldn't work anyway. Typically if you want a certain class to be allocated a certain way, you make the ctors private and make a public, static "create" function which allocates the object and returns a pointer.
wow Disch, Thanks for the amazing explanation. I guess set_new_handler will work for what I want, because I would hate to write even try catch again and again. All I want is my program to exit gracefully in case it cannot allocate memory.
Do you think I am going in the right direction? Or should I always use try catch around new ?
You don't need to try catch again and again. If you dont' want an abrupt crash, you can do a graceful catch. And if you're going to have the same handler throughout the program, you only need to do it once. That's the beauty of exceptions:
I wouldn't even bother trying to catch bad_alloc as the result of an OOM condition. The problem is that
there is almost nothing you can do to recover from it. If you are truly out of memory, then even a
simple cout statement may not work because behind the scenes the I/O stream library might attempt
to allocate memory for the print statement and that will of course also fail and cause a second,
uncatchable, bad_alloc to be thrown.
Furthermore, some OSes use an optimistic allocation strategy which means that new can return a
valid address, but the first write to each "allocated" page might fail due to an OOM condition. This
is because all new does is ensure there is a space big enough in your process' virtual address
space. It does not ensure that enough physical memory is available. Rather, it backfills the
virtual address space with physical pages on demand (which is why the first access could bomb
out).