Monday, April 11, 2005

Alloc callo(u)sness

For folks migrating from the realms of C to the expanse of C++ - don't be surprised if you seldom see malloc, calloc, realloc and free. The substitutes are new and delete. The key difference is while the alloc family are usually library level routines, new and delete are a language feature(They are 'operators' andnot functions).

Okay - Even beginner C++ programmers would know the usage of new and delete.

// C style
int * ptr = (int *)malloc(0x100000 * sizeof(int));

// C++ way of doing the same
int * ptr = new int[0x100000] ;

Notable differences between the 2 usages are -
1) No need to cast the pointer to appropriate type incase of new.
2) No need to specify the size of the type in case of new.

Pretty easy - huh?! Yes - that's all there is to that.But, if you're a seasoned C programmer, you'd definitely protect yourself from the untold misery of allocation failures by checking the pointer against NULL.

// C - I don't want to fall into a pit!
if( !ptr )
{
  // Sorry mate! Allocation has failed
  // Do the needful
}

Its the same in C++ too. Gods did not empower the language with unlimited memory space. Its the machine that the program runs on that its dependent on. But the way this is notified is by throwing an exception of type 'std::bad_alloc'. If you want to be safe,you'll have to catch that exception and deal with it.

// C++ - exception handling
try {
  int * ptr = new int[0x100000];
} catch( std::bad_alloc )
{
  // Alloc failed
  // If we can't do anything - propagate the
  // exception along. It'll cause an abort
  // down the line...
  throw;
}

"Hey this trying to allocate, catching an exception,handling it, if not propagating it, seems to be quite complicated for me. Is there something simpler?!" Yes there is. You know, you might be right. Exception handling can be quite expensive due to the unwinding semantics. Even I don't know what it means or does. Actually, before exceptions, this was the way, failed allocations were to be handled.

// C++ - older C style handling
int * ptr = new (std::nothrow) int[0x100000];
if (!ptr )
{
  // Same as C style handling!
}

Well - this is simple enough. Even though this is just a minute detail, not many people tend to know this.Well - now they do :-)

3 comments:

  1. when C++ exceptions are propagated even destructors for local objects are called the stack unwinding refers to the call stack unwinding when the throw is being propagated back to the callers... thats why its expensive...

    C exception handling is generally done using setjmp/longjmp mechanism, u would just do a jump to the exception handlers and be done with it..

    ReplyDelete
  2. Hmm... guessed so - C++ is pretty strict with proper construction and destruction of objects. It makes sense 'cos it does not have in-built garbage collection mechanism.

    Thanks John for dropping in a comment :-)

    ReplyDelete
  3. me YASE (yet another software enginner) ... actually a friend of avinash .. saw u on orkut but dont know how i came to ur blog.. from some kanishka' blog i guess

    ReplyDelete

What I want to say is: