RADE

C++ Source Checker

mkCheckSource Null Pointers Phase 1 Checks

Testing source code in the CAA V5 environment
Technical Article

Abstract

This article describes the checks relative to NULL Pointers Part 1. These checks are identified by LCDMNI, LCLVNI, LCDMMN, LCLVMN, LCVMNA, LCLVMNAR, LCVMNAAR, LCLVMNAC, LCVMNAAC.


Problematic

Managing pointers Lifecycle is not as easy as it seems to be [1]. How difficult can it be to debug an invalid pointer or an assert due to a NULL pointer.
To prevent these errors, two different types of checks are made by CSC:

This article deals only with NULL Pointers Part 1.
See [2] for NULL Pointers Part 2.

[Top]

Checks

Principle

Data Members

CSC has the knowledge of every data member of every class. For each Data member of type pointer, CSC checks:

Local Variables

CSC has the knowledge of every local variable. For each Local Variable of type pointer, CSC checks:

Argument Variables

CSC has the knowledge of every argument variable of functions or methods. For each Argument Variable of type pointer, CSC checks:

[Top]

Checks for Initialization

LCDMNI

LCDMNI stands for LifeCycle: Data Member Not Initialized.

An error of type LCDMNI is reported when:

As the data member is not set, we can not test it against NULL to know if it is valid or not.

Example LCDMNI-1

The Data Member is not initialized.

Let's take the following class:

class CATTest01
{
  CATBaseUnknown* _data;
  CATTest01();
  ...;
};

The following code will report a LCDMNI Error:

CATTest01::CATTest01()
{
}

The correct code is:

CATTest01::CATTest01() : _data(NULL) {}

or:

CATTest01::CATTest01() 
{
  _data= NULL;
}

Example LCDMNI-2

The Data Member is not initialized before use.

Let's take the following class:

class CATTest02
{
  CATBaseUnknown* _data;
  CATTest02();
  ...;
};

The following code will report a LCDMNI Error:

CATTest02::CATTest02()
{
  CATBaseUnknown* localVar= _data;
  ...
}

The correct code is:

CATTest02::CATTest02()
{
  _data= ...;  // Retrieve _data
  CATBaseUnknown* localVar= _data;
}

_data MUST be initialized before use.

Example LCDMNI-3

The Data Member is not initialized before use.

Let's take the following class:

class CATTest03
{
  CATBaseUnknown* _data;
  CATTest01();
  ...;
};

The following code will report a LCDMNI Error:

CATTest03::CATTest03()
{
  functionForUse( _data );
  ...
}

The correct code is:

CATTest03::CATTest03()
{
  _data= NULL;  // Or retrieve _data: _data= ...;
  functionForUse( _data );
  }

_data MUST be initialized before use.

LCLVNI

LCLVNI stands for LifeCycle: Local Variable Not Initialized.

An error of type LCLVNI is reported when:

As the variable is not set, we can not test it against NULL to know if it is valid or not.

Example LCLVNI-1

The Local Variable is not initialized before use.

The following code will report a LCLVNI Error:

...
CATI2DDitto *ditto;
HRESULT hr = myDittoPtr-> QueryInterface(IID_CATI2DDitto, (void **)&ditto);
...

The correct code is:

...
CATI2DDitto *ditto= NULL;
HRESULT hr = myDittoPtr-> QueryInterface(IID_CATI2DDitto, (void **)&ditto);
...

Example LCLVNI-2

The Local Variable is not initialized before use.

The following code will report a LCLVNI Error:

...
CATDocument *aDocument; 
HRESULT hr = CATDocumentServices::Open (PathDoc, aDocument);
...

The correct code is:

...
CATDocument *aDocument= NULL; 
HRESULT hr = CATDocumentServices::Open (PathDoc, aDocument);
...

[Top]

Checks for Reset C++ oriented

The aim of these checks is to ensure the assignment to NULL of a pointer after C++ specific calls which alter the validity of the pointer.

LCDMMN

LCDMMN stands for LifeCycle: Data Member Missing NULL.

An error of type LCDMMN is reported when:

Every data member of type pointer must be set to NULL in destructor (after last use).

Example LCDMMN-1

The Data Member is not reset in destructor.

Let's take the following class:

class CATTest04
{
  CATBaseUnknown* _data;
  CATTest04();
  ~CATTest04();
  ...;
};

The following code will report a LCDMMN Error:

CATTest04::~CATTest04()
{
}

The correct code is:

CATTest04::CATTest04()
{
  _data= NULL;
}

Example LCDMMN-2

The Data Member is not reset in destructor after last use.

Let's take the following class:

class CATTest05
{
  CATBaseUnknown* _data;
  void check();
  CATTest05();
  ~CATTest05();
  ...;
};

The following code will report a LCDMMN Error:

void CATTest05::check()
{
  if( _data ) 
    cout << "_data is not null " << endl;
}

CATTest05::~CATTest05()
{
  _data= NULL;
  check();
}

As the method check() uses the data member _data, CSC will see that data member _data is first set to NULL, then used in the destructor.

The correct code is:

void CATTest05::check()
{
  if( _data ) 
    cout << "_data is not null " << endl;
}

CATTest05::~CATTest05()
{
  check();
  _data= NULL;
}

LCLVMN

LCLVMN stands for LifeCycle: Local Variable Missing NULL.

An error of type LCLVMN is reported when a local variable is:

If the variable is not set to NULL after delete, we got a non null pointer which is not valid !

Example LCLVMN-1

The Local Variable is not reset after delete.

The following code will report a LCLVMN Error:

CATDbDriverCol *driverCol=0;
... // use driverCol
delete driverCol;
CATDbDriverDatabase *driverDB = CATDbDriverDatabase::Create(vendor);
driverDB-> CreateCol(driverCol);

The correct code is:

CATDbDriverCol *driverCol=0;
... // use driverCol
delete driverCol;
driverCol= NULL;
CATDbDriverDatabase *driverDB = CATDbDriverDatabase::Create(vendor);
driverDB-> CreateCol(driverCol);

LCVMNA

LCVMNA stands for LifeCycle: Variable Missing Null Assignment.
LCVMNA is for argument variables and data members the equivalent of LCLVMN for local variables

An error of type LCVMNA is reported when an argument variable or a data member is:

If the variable is not set to NULL after delete, we got a non null pointer which is not valid !

Example LCVMNA-1

The Data Member is not reset after delete.

Let's take the following class:

class CATTest06
{
  CATFont* _font;
  void clean();
  ...;
};

The following code will report a LCVMNA Error:

void CATTest06::clean()
{
  if( _font ) 
    delete _font;
}

The correct code is:

void CATTest06::clean()
{
  if( _font ) {
    delete _font;
    _font= NULL;
  }
}

Example LCVMNA-2

The argument variable is not reset after delete.

The following code will report a LCVMNA Error:

void delete_dimension(dimension*& dim)
{ 
  delete(dim);
}

The correct code is:

void delete_dimension(dimension*& dim)
{ 
  delete(dim);
  dim= NULL;
}

[Top]

Checks for Reset CATIA specific

The aim of these checks is to ensure the assignment to NULL of a pointer after CATIA specific calls which alter the validity of the pointer.

LCLVMNAR

LCLVMNAR stands for LifeCycle: Local Variable Missing NULL Assignment after Release. It is a particular case of error LCLVMNAC.

An error of type LCLVMNAR is reported when a local variable is:

If the variable is not set to NULL after a call to Release, we got a non null pointer which is not valid !

Example LCLVMNAR-1

The local variable is not reset after Release, the following code will report a LCLVMNAR error:

if (result) {
   AddScope(result);
   result->Release();
}

The correct code is:

if (result) {
   AddScope(result);
   result->Release();
   result = NULL;
}

Example LCLVMNAR-2

The local variable is reused after Release and before assignement to NULL, the following code will report a LCLVMNAR error:

if (_Parent) {
   _Parent-> Release();
   hr = _Parent-> QueryInterface( IID_CATISketchingElement, (void **) &geom );
   _Parent = NULL;
}

The correct code is:

if (_Parent) {
   hr = _Parent-> QueryInterface( IID_CATISketchingElement, (void **) &geom );
   _Parent-> Release();
   _Parent = NULL;
}

[Top]

LCVMNAAR

LCVMNAAR stands for LifeCycle: Variable Missing Null Assignment After Release.
LCVMNAAR is for argument variables and data members the equivalent of LCLVMNAR for local variables, and is a particular case of error LCVMNAAC.

An error of type LCVMNAAR is reported when an argument variable or a data member is:

If the variable is not set to NULL after Release, we got a non null pointer which is not valid !

Example LCVMNAAR-1

The data member is not reset after Release.

Let's take the following class:

class CATTest07
{
  CATBaseUnknown* _data;
  void clean();
  ...;
};

The following code will report a LCVMNAAR error:

void CATTest07::clean()
{
  if( _data ) 
    _data->Release();
}

The correct code is:

void CATTest07::clean()
{
  if( _data ) {
    _data->Release();
    _data = NULL;
  }
}

Example LCVMNAAR-2

The argument variable is not reset after delete, the following code will report a LCVMNAAR error:

void delete_sphere(CATSphere*& sphere)
{ 
  sphere->Release();
}

The correct code is:

void delete_sphere(CATSphere*& sphere)
{ 
  sphere->Release;
  sphere = NULL;
}

[Top]

LCLVMNAC

LCLVMNAC stands for LifeCycle: Local Variable Missing NULL Assignment after Call to delete method.

Some classes must not be deleted via delete or Release but have a specific destruction method. A pointer to an instance of one of these classes (or of an inherited class) have to call the delete method corresponding to its class to be deleted. After the call, the pointer must be set to NULL or to a valid data, in order to preserve equivalence between validity of the pointer and a value not NULL.

The list of each class concerned and its associated delete methods is provided in the setting files, see LifeCycle_DeleteMethods section.

An error of type LCLVMNAC is reported when a local variable:

If the variable is not set to NULL after a call to a delete method, we got a non null pointer which is not valid !

Example LCLVMNAC-1

Let's assume that a pointer on a CATRep instance must be deleted using the method Destroy().

The local variable is not reset after call to delete method Destroy() and before use, the following code will report a LCLVMNAC Error:

CATRep * rep = new CATRep();
 ... // use of rep
rep->Destroy();
CATManipulator* manip = rep->GetManipulator();

The correct code is:

CATRep * rep = new CATRep();
 ... // use of rep
CATManipulator* manip = rep->GetManipulator();
rep->Destroy();
rep = NULL;

[Top]

LCVMNAAC

LCVMNAAC stands for LifeCycle: Variable Missing Null Assignment After Call to delete method.

LCVMNAAC is for argument variables and data members the equivalent of LCLVMNAC for local variables.
The list of each class concerned and its associated delete methods is provided in the setting files, see LifeCycle_DeleteMethods section.

An error of type LCVMNAAC is reported when an argument variable or a data member:

If the variable is not set to NULL after a call to a delete method, we got a non null pointer which is not valid !

Example LCVMNAAC-1

Let's assume that a pointer on a CATRep instance must be deleted using the Destroy method.

Let's take the following class:

class CATTest08
{
  CATRep* _rep;
  void clean();
  ...;
};

The data member is not reset after call to delete method Destroy(), the following code will report a LCVMNAAC error:

void CATTest08::clean()
{
  if( _rep ) 
    _rep->Destroy();
}

The correct code is:

void CATTest08::clean()
{
  if( _rep ) {
    _rep->Destroy();
    _rep = NULL;
  }
}

Example LCVMNAAC-2

The argument variable is not reset after call to delete method Destroy(), the following code will report a LCVMNAAR error:

void delete_rep(CATRep*& rep)
{ 
  rep->Destroy();
}

The correct code is:

void delete_rep(CATRep*& rep)
{ 
  rep->Destroy();
  rep = NULL;
}

[Top]

Relative sections in setting files

For a more complete description of Setting Files, see [3].

LifeCycle_DeleteMacro

This section is located in: SettingsSet > OptionLists > LifeCycle_OptionLists

This section contains a list of Macro like:

#define DELETEMACRO(ptr) if (ptr) {delete(ptr); ptr=NULL;} 

This list is used in particular when a macro of this type is used to reset a Data Member in a destructor. This prevent from generating an invalid LCDMMN error.

[Top]

LifeCycle_NewMacro

This section is located in: SettingsSet > OptionLists > LifeCycle_OptionLists

This section contains a list of Macro like:

#define NEWMACRO(ptr) ptr= new CL();

This list is used in particular when a macro of this type is used to initialize a Data Member in a constructor. This prevent from generating an invalid LCDMNI error.

[Top]

LifeCycle_DeleteMethods

This section is located in: SettingsSet > OptionLists > LifeCycle_OptionLists

This section contains a list of Call. Each Call describes the delete method of a class:

ClassName
The name of the class (no ClassName means that it is a function)
MethodOrFunctionSign
The signature of the function or method

Example 1:

ClassName            CATRep
MethodOrFunctionSign Destroy

This means that the method Destroy deletes CATRep instances. Thus each CATRep instance must be set to null (or to a valid data) after a call to Destroy.

[Top]


In Short

All checks included in Pointers Null Part 1 insure that no dangling pointer will be present at runtime.

[Top]


References

[1] CAA V5 C++ Coding Rules
[2] Null Pointers Part 2 Checks
[3] Setting Files
[Top]

History

Version: 1 [May 2001] Document created
[Top]

Copyright © 2000, Dassault Systèmes. All rights reserved.