wrapper function for new

Nov 15, 2009 at 7:33pm
Hi Guys,

Actually, when we allocate memory using new we do it something like

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 
 struct node { 
     node() { 
         cout<<"Constructor";
    } 
    int i ; 
} ; 

int main() { 

   node *p = new node ; 
   if ( p == NULL) { 
        cout<<"error: cannot allocate memory \n";
        exit(-1) ; 
    } 

    return 0; 
}


So, I don't want to check everytime after allocating a memory that whether the pointer is equal to NULL for error. So I created this wrapper function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 

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


Any help would be great.

Thanks a lot
Last edited on Nov 15, 2009 at 7:38pm
Nov 15, 2009 at 8:12pm
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 = new int;
  // 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:

http://cplusplus.com/reference/std/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.
Nov 15, 2009 at 8:32pm
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 ?

Please let me know
Nov 15, 2009 at 9:09pm
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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <exception>

using namespace std;

void FooBar();

int main()
{
  try
  {
    // do stuff here and it gets caught:
    int* foo = new int[100];
    delete[] foo;

    // call another function:
    FooBar();
  }
  catch(std::exception& exc)
  {
    cout << "Fatal Error in program:\n" << exc.what();
    return 1;
  }
  return 0;
}


void FooBar()
{
  // if an exception gets thrown here, it still gets caught by above catch block!
  int* bar = new int;
  delete bar;
}


etc.

By putting main inside a single try-catch block, you can catch all exceptions anywhere in the program (or really... anywhere in the thread)
Nov 15, 2009 at 10:07pm
Thanks so much for clearing my doubt Disch.
Nov 16, 2009 at 1:09pm
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).
Topic archived. No new replies allowed.