C++ new() operator

June 28, 2012 at 7:17 pm | Posted in C++, Programming | Leave a comment
Tags: , , ,

I was working on adding some features to a software written as a mixture of C and C++ and I came to realize many C++ programmers write C in C++. Take a look at this:

#include <iostream>
#include <new>

int main()
{
  char * t = new char[1];

  if(!t) 
    {
      printf("Memory Exhausted\n");
      exit(EXIT_FAILURE);
    }

  t[0] = 'A';

  printf("t[0] = %c\n", t[0]);
  return 0;
}

Everything looks fine and g++ (on RHEL 5) even compiles/runs with flags (-ansi -pedantic -Wall -Wextra) and without any warning/error. Program just seems to be technically correct (which it is seems like but isn’t) and prints the value inside array as expected. Now let us take a more basic look at this. Why we are using printf() in a C++ program when C++ has its own standard library ? The program we have writen is actually C in C++. It is like using a powerful mechanism and throwing all the powerful tools/methods away because you don’t want to know about them. Many industrial programmers don’t want to know about it because life goes on fine without knowing about it and they are still earning much higer salaries without knowing it (and they will keep on increasing their monthly income by impressing HR guys with a bag of languages and big projects on their Resumes). Hence Why bother ? Wrong reasons. If you are really looking for laziness then find it elsewhere because laziness equals to the amount of bugs in programming. Rewrite it the C++ way:

#include <iostream>
#include <new>

int main()
{
  char * t = new char[1];

  if(!t) 
    {
      std::cerr << "Memory Exhausted" << std::endl;
      exit(EXIT_FAILURE);
    }

  t[0] = 'A';
  std::cerr << "t[0] = " << t[0] << std::endl;

  return 0;
}

It is still not C++. What we call it now is a mixture of C and C++ provided the programmer does not know about C++ much. He was basically a C programmer and was either forced to use C++ compiler or was too lazy to know C++. Again it compiles/runs fine as it looks technically correct. check out new operator in section 18.6.1 of current C++ standard (you can check out draft of the standard, just google for N3337.pdf). new does not return NULL, hence the check is wrong. new throws bad_alloc() if it can’t allocate memory. Hence the technically correct version looks like this:

#include <iostream>
#include <new>

int main()
{
  char * t;

  try { t = new char[1]; }
  catch(bad_alloc)
    {
      std::cerr << "Memory Exhausted" << std::endl;
      exit(EXIT_FAILURE);
    }
  
  return 0;
}

This will never compile. Why ? Because you did not mention where bad_alloc is coming from. It is in standard library, hence you need to use std::bad_alloc. If you think you simply dump the whole standard namespac by using using namespace std in there, then you really need to read C++ FAQs before writing C++ programs any further. You need to think why I am writing std::cout instead of usual cout used by typical Indian programmers. Let us try one more time:

#include <iostream>
#include <new>

int main()
{
  char * t;

  try { t = new char[1]; }
  catch(std::bad_alloc)
    {
      std::cerr << "Memory Exhausted" << std::endl;
      exit(EXIT_FAILURE);
    }

  t[0] = 'A';
  std::cout << "t[0] = " << t[0] << std::endl;

  return 0;
}

This seems like pure C++. Yes, it is. Sure ? We still have one general programmig problem remaining to be solved. If you call exit() then you are not being practical, e.g. you wrote a client which connects to a server. One of the users of your software is connected and suddenly he is out of memory, then you program will just disconnect without saying a bye. Server will not like it and may log it as an error or will wait for an automatic timeout.

That was a general exmaple, let us look at more technical example. When a game adjusts your resolution to 640×480 and resets it back to normal (say 1280×1024), it will call destructor on 640×480 in resetting but it will not do so because exit() will not call the destructor, you will get stuck in a low resolution screen. It happens when some games crash without throwing an exception and rolling back the stack. So what do you do ? Let us try one last time to write pure C++ code 🙂

#include <iostream>
#include <new>

int main()
{
  char * t;

  try { t = new char[1]; }
  catch(std::bad_alloc)
    {
      std::cerr << "Memory Exhausted" << std::endl;
      return EXIT_FAILURE;
    }

  t[0] = 'A';
  std::cout << "t[0] = " << t[0] << std::endl;

  return 0;
}

NOTE: There is still a way if you want to check for NULL (instead of catch()ing an exception). You can use the nothrow version of new operator which returns a NULL pointer instead of throwing an exception but you have to mention it explicitly.

 


Copyright © 2012 Arnuld Uttre, Village – Patti, P.O – Manakpur, Tehsil – Nangal, Distt. – Ropar, Punjab (INDIA)

Verbatim copying and distribution of this entire article are permitted worldwide, without royalty, in any medium, provided this notice, and the copyright notice, are preserved.

Advertisements

Leave a Comment »

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.
Entries and comments feeds.

%d bloggers like this: