My Development Space

Yet another Space on C++,Java,Open Source & Software Development!

Pointer++ : A look at Three Enhanced Pointer Libraries

with one comment

What’s wrong with Normal C++ Pointers ?

Normal C/C++ pointers give a great power to the programmer. They allow the programmer to control memory blocks and write efficient code.

Yet, and as the old saying: ” with Great Power .. Comes Great Responsibilty!”, C++ pointers are hard to use and even harder to debug.

There are 3 main issues that make pointers such a pain:

  1. Memory Leaks : that is, Forgetting to release the memory location held by the pointer when done. check out the folloing Code:

    int sumArray()
    {
    int sum = 0;
    int* myArr = new int[10000];
    //Do some work here with the pointer to figure out the sum
    return sum;
    }

    We allocated an array of 10000 numbers BUT WE FORGOT to delete it. So, after the function gets out of the scope, the pointer itself in the programs stack will be deleted leaving the data associated with him in the heap as carbage.

  2. Dangling Pointer: This issue occurs when the memory location pointed at by one pointer is no longer valid or allocated. To demonstrate this issue, take a look at the following Code:

    SomeObj *bad_ptr1, *bad_ptr2;
    char *bad_ptr3;
    bad_ptr1 = new SomeObj();
    bad_ptr2 = bad_ptr1; // both bad_ptr1, bad_ptr2 point to the same memory location
    delete bad_ptr2; // At this Moment, bad_ptr1 points to invalid deallocated memory location, thus bad_ptr1 is a DANGLING POINTER
    {
    char someVal;
    bad_ptr3 = someVal;
    }
    //Now, after the block has been executed, and the local scope variable falls out of scope, bad_ptr3 is a DANGLING POINTER

    AS you can see, bad_ptr1, bad_ptr2 point to the same memory location. bad_ptr2 deallocated this memory segment by calling delete;
    So, if bad_ptr1 ties to use this piece of memory - which was already deallocated, it will casue the program to crash and issue a "Segementation Fault" . The Same situation repeats with bad_ptr3. it pointed to a local variable someval. When someVal falls out of scope, it got deleted automatically, So, bad_ptr3 is now pointing to an invalid memory location.

  3. Double Deallocation: it is a special case of Dangling pointer. if two pointers point to the same memory location and both deleted it. this will also cause an error. I compiled and ran a simple program that does so. and gcc 4.3 issuesd the following runtime error: "double free or corruption".

TheSolution: Enhanced Pointers

We will discuss three types of enhanced pointers that may help overcome the 3 pointer issues.

  1. C++ Standard Library's auto_ptr:

    auto_ptr is a class template provided by the C++ standard Library . That means you don't need to use any additional libraries to start using it. just include the <memory> include file.
    What makes the auto_ptr so special is it solves , by default. the problem of memory leaks. You don't have to worry about where to delete your pointer. It will automatically deallocate the memory location once the pointer itself is destroyed or goes out of scope.
    To learn how to define and use an auto_ptr, have a look at the following code:

    int *i = new int(89);
    auto_ptr x(i);
    cout< cout<<*(x.get())<

    auto_ptr is also a greedy class. It Must make sure it is the only pointer pointing to a given piece of memory. So if  another auto_ptr copies it, it will automatically point to NULL. this feature is useful to prevent Modifying the data from outside its scope, thus preventing Dangling pointers and Double Deallocation.
    take a look at the following code segment:

    int *i = new int(89);
    auto_ptr gready_ptr(i);
    auto_ptr other_ptr= gready_ptr; // gready_ptr will automatically be NULL
    cout<

    auto_ptr Pros:

    • memory leaks by automatically deleting the memory once the auto_ptr is destroyed.
    • prevents more than one auto_ptr s from pointing to the same Object.

    auto_ptr Cons:

    • Doesn't handle multiple pointers to the same object.
    • You can't mix normal pointers with auto_ptr or cast auto_ptr back to normal pointers.
  2. QT's QPointer - QT's Guarded Pointer:

    Qt is a cross-platform application development framework, widely used for the development of GUI programs. Qt is most notably used in KDE, Opera, Google Earth, Skype, Qt Extended, Adobe Photoshop Album, VirtualBox and OPIE.
    QPointer is a part of the Qt  toolkit. It was designed to overcome the problem of Dangling pointers only. a QPointer object behaves like a normal C++ pointer T*, except that it is automatically set to 0 when the referenced object is destroyed. You need to install the QT toolkit library in order to use QT's QPointer. The refrenced Class Must be a subclass of the QObject class. Have a look at the following code to see QPointer in action:

    QPointer label = new QLabel; // QLabel is a class for UI label extending QObject
    label->setText("Status:");
    ...
    if (label) // if label was deallocated somewhere else, label will point to NULL thus it will not enter the if block.
    label->show();

    QPointer's Pros:

    • prevents Dangling pointers.
    • Fully Compatible with the normal C++ pointer. you can freely mix guarded and unguarded pointers as  a guarded pointer will automatically cast to a T *.

    QPointer's Cons:

    • Doesn't handle memory leaks issue, So you still have to recheck your code for any missing delete statements.
    • Works only as a part of the QT library, You can't  use it in a simple non-QT application.
    • You can only use it refrence Objects extending the QObject class. You can't use it to reference primitive data types or Classes not extending the QObject.
  3. Boost's Smart Pointer Family:

    The Boost C++ Libraries are a collection of  open source libraries that extend the functionality of C++.Smart pointers are objects which store pointers to dynamically allocated (heap) objects. They behave much like built-in C++ pointers except that they automatically delete the object pointed to at the appropriate time.They can also be used to keep track of dynamically allocated objects shared by multiple owners.
    Boost provides the following smart pointer implementations:

    1. scoped_ptr:
      a pointer automatically deleted when it goes out of scope.
      scoped_ptr is uncopyable, thus no assignments possible. The following Code demonstrates the specs of the scoped_ptr:

      #include
      #include
      using namespace std;
      using namespace boost;

      int fn()
      {
      boost::scoped_ptrptr(new int(90));
      *ptr=300;
      cout<<*ptr< boost::scoped_ptrptr2(new int(900) );
      ptr2 = ptr; // COMPILE ERROR! You can't copy the scoped_ptr to another one
      // NO NEED to delete ptr, it will autodelete itself when it goes out of scope
      return 0;
      }

      scoped_ptr Pros:

      • Handles Both Memory leaks and Dangling Pointers issues.
      • Very fast and efficient.
      • Safer than C++ STL auto_ptr as it is uncopyable.

      scoped_ptr Cons:

      • Doesn't handle multiple pointers to the same object.
      • Cannot be used in C++ Standard Library containers. Or hold a pointer to an Array. Use scoped_array instead.
      • Not compatible with normal C++ pointers. can't mix and cast between types.
    2. shared_ptr:
      a pointer to a dynamically allocated object. The object pointed to is guaranteed to be deleted when the last shared_ptr pointing to it is destroyed or reset. The following code may provide you with a brief information about its features:

      include
      #include
      using namespace std;
      using namespace boost;

      int fn()
      {
      boost::shared_ptrptr1(new int(90));
      boost::shared_ptrptr2 = ptr; // copying is allowed for shared pointers, So both ptr1 & ptr2 point to the same memory segment
      cout<<*ptr2< *ptr2 = 7000; // now both ptr1 & ptr2 point to 7000
      cout<<*ptr< ptr.reset(); // means: delete ptr;
      cout<<*ptr2< return 0; // ptr was deleted previously - when calling reset(), and ptr2 is now out of scope, SO, the memory location IS DELETED AUTOMATICALLY
      }

      shared_ptr Pros:

      • Handles Both Memory leaks and Dangling Pointers issues.
      • Handles multiple pointers to the same object with reference counter.

      shared_ptr Cons:

      • Cannot correctly hold a pointer to a dynamically allocated array.Use shared_array instead.
      • Not compatible with normal C++ pointers. can't mix and cast between types.

    Final Conclusion:

    • You can overcome pointers issues using the new pointer types.
    • If you don't want to use any external libraries, STL's auto_ptr is the best solution for you.
    • If you are writing a QT application, QPointer will be a very helpful utility.
    • If it is OK with you to import external libraries, boost smart pointer family is the ultimate solution.

Written by topquarck

May 23, 2009 at 12:33 am

Posted in c++

Tagged with , , ,

One Response

Subscribe to comments with RSS.

  1. “enhanced pointers” are just one example of an important underlying principle: A resource (including memory) should be managed by exactly one class at a time. Example: std::string and other containers. They manage dynamically allocated objects internally. The user doesn’t have to worry about it.

    This is what RAII/RRID is all about (resource acquisition is initialization / resource reclamation is deinitialization).

    If you honor this principle you don’t need those “enhanced pointers” in many situations. Sometimes, they are very useful, though. :)

    pizer

    May 23, 2009 at 1:09 pm


Leave a Reply