Thursday, 5 March 2015

Dangling Pointers with examples

Dangling Pointers in cpp with examples:

Dealing with the memory is the most important task for the programmer. Some cases we may face some problems like the application runs 10 times and it crashes 3 times out of 10. We do not predict the problem that we are getting, to track that problem we will search for another way. That is we will decide to run that application in different machines.

In this situation also we get the result like that the application may run in 5 systems out of 8, the remaining 3 systems application may crash.

Nine times out of ten, when you're told that a program 'sometimes crashes', those crashes are random, and apparently they do not depend on a particular user's action. This one is no exception.

If this situation come I will go and search for some major points.

1. A memory allocation (malloc, calloc, strdup, and realloc) returns NULL, and this return value is ignored.
2. A resource allocation (fopen, or CreateFile, for instance) returns NULL (or INVALID_HANDLE_VALUE), and this return value is ignored.
3. A race condition: one thread is trying to use a resource that was released by another thread.
4. A memory corruption, for instance a buffer overflow.
5. A dangling pointer.

Coming to the main picture of the topic: DANGLING POINTERS

First of all what are dangling pointers?

 A dangling pointer is a pointer that points to invalid data or to data which is not valid anymore.

Let us see the situations that we can get the dangling pointers
Class *Obj1 = new Class();
Class *Obj2 = Obj1;
delete Obj1;
Obj1 = nullptr;
Obj1 *method() {
  Obj1 Obj1;
  return &Obj1;
Obj1 *Obj2 = method();
Dangling pointers arise during object destruction, when an object that has an incoming reference is deleted or deallocated, without modifying the value of the pointer, so that the pointer still points to the memory location of the deallocated memory.

The below are the causes of Dangling pointers:

Void myFunc () {
char *pcchChar = NULL;
if (condition) {
char pchval;
       pcchChar = &pchval;
Here the char pchVal is out of scope, unable to ccess the data that is available in the pointer. Here the pccchChar is the dangling pointer. To reso;ve the problem we can allocate the NULL to the pcchChar before the inner block is exited.


Another frequent source of dangling pointers is a jumbled combination of malloc() and free() library calls: a pointer becomes dangling when the block of memory it points to is freed.
void FuncTestDangling()
    char *pcObj1 = malloc(A_CONST);
    /* ... */
    pcObj1 = NULL;
    /* ... */

In the above case

   free(pcObj1; pcObj1 now becomes a dangling pointer
    pcObj1 = NULL; pcObj1 is no longer dangling


An all too common misstep is returning addresses of a stack-allocated local variable: once a called function returns, the space for these variables gets deallocated and technically they have "garbage values".

int *FuncTestDangling(void)
    int ipcIVal = 1234;
    /* ... */
    return &ipcIVal;

Attempts to read from the pointer may still return the correct value (1234) for a while after calling FuncTestDangling, but any functions called thereafter will overwrite the stack storage allocated for ipcIVal with other values and the pointer would no longer work correctly. If a pointer to ipcIVal must be returned, ipcIVal must have scope beyond the function—it might be declared as static.

Let us see the simple project
#include "stdafx.h"
struct MyInterface
    virtual bool IsVerify () = 0;
    virtual double MyFunc (int iVal, double dVal) = 0;
    virtual ~MyInterface () { };
class MyClass : public MyInterface
    int iValA;
    double iValB;
    virtual bool IsVerify ()
       { return true; }
    virtual double MyFunc (int i, double d)
       { return i * d; }
    double Mul ()
       { return iValA * iValB; } 
    MyClass ()
       { iValA = 128; iValB = 4.14513; }
    ~MyClass ()
       { iValA = 21; iValB = 12.0; }
void test (MyClass *ocObj)
    MyInterface *pI = ocObj;

    printf ("ocObj (iValA.k.iValA pI) is %s; the size of MyClass is %d bytes; the int takes %d, the double %d, and the vtable pointer %d.\n",

             pI->IsVerify () ? "alive": "dead", sizeof MyClass, sizeof (int), sizeof (double), sizeof (void *));

    ocObj->iValA = 183;

    ocObj->iValB = 0.21;

    printf ("MyInterface::MyFunc address is %p\n", &MyInterface::MyFunc);

    printf ("pI->MyFunc(%d, %f) = %f\n", 23, 52.05, pI->MyFunc (45, 52.05));

    delete ocObj;

    printf ("Not crashed yet: ocObj->iValA is %d (0x%MyClass), ocObj->iValB is %e (0x%I64X)\n", ocObj->iValA, ocObj->iValA, ocObj->iValB, ocObj->iValB);

    ocObj->iValB = 111.222333;

    printf ("Still not crashed; ocObj->iValB is %f\n", ocObj->iValB);

    printf ("MyClass::MyFunc address is %p\n", &MyClass::MyFunc);                    

    ocObj->iValA = 122;

    printf ("ocObj->Mul() returned %f. Are we crashing yet?\n", ocObj->Mul ());

    printf ("ocObj is %s.\n", ocObj->MyClass::IsVerify() ? "UNDEAD!": "dead");   


int main (int argc, char* argv[])

    test (new MyClass);
    getchar ();
 return 0;
The program will get crashed and the result is
HEAP[DanglingPointer.exe]: HEAP: Free Heap block 4f6fc8 modified at 4f6ff4 after it was freed

DanglingPointer.exe has triggered a breakpoint.

No comments: