Detecting Calling Methods On Deleted Objects

Using Memory Validator to detect when you are calling methods on objects that you’ve already deleted. 

A common problem when writing C++ applications is the data corruption and/or application crash that is associated with using objects that have already been deleted. This error can happen when a dynamically allocated object is deleted, but the pointer to the object is not set to NULL, or there are multiple pointers to the object in the application and not all the pointers have been set to NULL. A simplified code fragment is shown below.

    someObject	*objPtr;

    // create the object

    objPtr = new someObject();

    // simulate doing some work

    objPtr->readData();

    callWorkerFunction1(objData);
    callWorkerFunction2(objData);

    objPtr->writeData();

    // finished with the object

    delete objPtr;

    // forgot to set the pointer to NULL 

    ... some more code

    // accidentally use the object, this is an error

    objPtr->calculateResults();

Often, the above code will lead to a crash at the point where the code is called. This is easy to debug.

What is not so easy to identify is when the call to calculateResults() doesn’t crash because the memory pointed to by objPtr is still a valid address. If calculateResults() modifies the memory pointed to by objPtr, one of three things can happen.

  1. The memory has not been reused by another dynamic allocation. The call to calculateResults() modifies memory not used by anyone else. No memory corruption occurs. However, depending on what calculateResults() does (for example, calling a virtual function, or a function pointer in the deleted memory) a crash may occur immediately.
  2. The memory has been reused (in part or in full) by another dynamic allocation. The call to calculateResults() modifies memory used by a different object. Memory corruption occurs. Depending on the nature of the memory corrupted, a crash may occur later in the application, at a location unrelated to the memory corruption occurring.Also, depending on what calculateResults() does (for example, calling a virtual function, or a function pointer in the deleted memory) a crash may occur immediately.
  3. If the function called does nothing more than return a constant value (TRUE, FALSE, NULL, an enumeration etc), program will have no bad side effects (indeed, a few MFC functions are coded to accept NULL “this” pointers). If this is the case you will have no knowledge (in the form of unexpected behaviour or crashed) of the error in your application.

As you can see, identifying occasions when a deleted object is use is a very useful ability.

Options

On the Deleted “this” tab of the settings dialog, select the Detect called functions for deleted C++ objects on the CRT heap check box. If you wish to see reports for NULL and invalid pointers, select the Report NULL “this” pointers and invalid”this” pointers check box.

Memory Validator deleted this settings

 

  • Start the nativeExample.exe application as normal.
  • On the Memory Errors menu, choose the Deleted this usage option. The following code will be executed:
        exampleClass	*ec;
        ec = new exampleClass();
        delete ec;
    
        // call method on class object that has been destroyed - this is an error
    
        ec->exampleMethod();
    
  • Memory Validator will detect the error and will display an error on the Memory tab. The image below shows the error report, after being expanded to show the source code.

Memory Validator deleted this detection

Fully functional, free for 30 days