Sunday, May 20, 2007

The STL is your friend

Everyone knows this little idiom in 'C'

  char * array = malloc(string_length+1);
  if(!array)
  {
    // do something to handle allocation failure.
  }
  // do the real work
  free(array);

So the C++ equivalent must be

  char * array = new char[string_length+1];
  if(!array)
  {
    // do something to handle allocation failure.
  }
  // do the real work
  delete array;

Actually -- no.

The first bug is that having used new[], this must be matched by a delete[] (otherwise you will land yourself with interesting heap corruption to track down). The second is the behaviour of new when memory is not available.

Unless you have gone through some contortions to set up your build (in which case you know what you are doing), memory allocation is raised as exception std::bad_alloc -- so take 2…

  char * array = NULL;
  try {
      array = new char[string_length+1];
  } catch (std::bad_alloc) {
    // do something to handle allocation failure.
  }
  // do the real work<
  delete [] array;

Better, but you're still doing some of the heavy lifting yourself. Better yet is (assuming that you are working on the allocated space as a mutable buffer)

  std::vector<char> array; // zero length vector on the stack
  try {
     array = std::vector<char>(string_length+1);
  } catch (std::bad_alloc) {
    // do something to handle allocation failure.
  }
  // do the real work

or, if you're actually working with a string that is to be read from

  std::string array; // zero length string on the stack
  try {
     array = std::string(my_nil_terminated_string);
  } catch (std::bad_alloc) {
    // do something to handle allocation failure.
  }
  // do the real work

where the buffer management is handed over to code already written and tested to do the job for you.

No comments :