RADE |
C++ Source Checker |
mkCheckSource Null Pointers Phase 2 ChecksTesting source code in the CAA V5 environment |
Technical Article |
AbstractThis article describes the checks relative to NULL Pointers Part 2. These checks are identified by LCDMMCBU, LCLVMCBU, LCAVMCBU, LCDMMCBU2, LCLVMCBU2, LCAVMCBU2. |
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:
These checks must insure that:
(pointer is VALID) <=> (pointer is NOT NULL)
These checks must insure that every pointer is tested against NULL before use.
This article deals only with NULL Pointers Part 2.
See [2] for NULL Pointers Part 1.
[Top]
In these checks, every variable (instance of class) of type pointer is followed. Each time a method (member function of the class) is called on the variable, CSC checks if the call is done in a safe branch of code against nullity of the pointer. If it is not, an error is reported. If CSC can not statically determine if the branch of code is safe, an error is reported.
Methods and functions in LifeCycle_SafeMethodsForMCBU cannot return a null pointer.
These checks are a subpart of the LC*MCBU ones. In these checks, each time a
method is called on a variable of type pointer, if the variable was previously
assigned via a function declared in an external framework (not the
current framework), and if the pointer may be null at this time, an error is
reported.
Pointers of type in LifeCycle_IgnoredClassesForMCBU2
are ignored.
These checks insure that the inter-framework interactions won't generate any runtime abort.
If the LifeCycle_UntrustableForMCBU2 list is not empty, the function must:
The default LifeCycle_UntrustableForMCBU2 section is empty: all the calls to a function declared in an external framework are analyzed, except calls of "safe" methods.
[Top]
LCLVMCBU stands for LifeCycle: Local Variable Missing Check Before Use.
An error of type LCLVMCBU is reported when:
If the assigning method returned a null pointer, a null pointer read will occur at runtime, leading to the abort of the program.
The local variable edgeCurve is not tested before use.
The following code will report a LCLVMCBU error:
... CATEdgeCurve* edgeCurve = NULL; vertices[vindex]->GetParamOnEdgeCurve(startEdge, edgeCurve, crvParam, side); edgeCurve-> Eval(crvParam, CATCrvEvalCommand::EvalFirstDerivative, NULL, &edgeTgt); ... |
The correct code is:
... CATEdgeCurve* edgeCurve = NULL; vertices[vindex]->GetParamOnEdgeCurve(startEdge, edgeCurve, crvParam, side); if( edgeCurve ) { edgeCurve-> Eval(crvParam, CATCrvEvalCommand::EvalFirstDerivative, NULL, &edgeTgt); ... } ... |
LCDMMCBU2 stands for LifeCycle: Data Member Missing Check Before Use.
An error of type LCDMMCBU is reported when:
If the assigning method returned a null pointer, a null pointer read will occur at runtime, implying the abort of the program.
The data member _pHole is not tested before use.
Let's take the following class:
class CATPrtCreateHoleCom { ... CATINewHole* _pHole; HRESULT CreateHole(void*); ...; }; |
The following code will report a LCDMMCBU error:
... HRESULT CATPrtCreateHoleCom::CreateHole (void *) { ... CATISpecObject_var hSpecLimit; _pHole-> GetLimit(hSpecLimit); _pHole->Release(); _pHole= NULL; ... // Use hSpecLimit } ... |
The correct code is:
... HRESULT CATPrtCreateHoleCom::CreateHole (void *) { ... CATISpecObject_var hHole= ...; // Retrieve hHole CATISpecObject_var hSpecLimit; if( _pHole ) { _pHole-> GetLimit(hSpecLimit); _pHole->Release(); _pHole= NULL; } ... // Use hSpecLimit } ... |
LCAVMCBU stands for LifeCycle: Argument Variable Missing Check Before Use.
An error of type LCAVMCBU is reported when:
If the assigning method returned a null pointer, a null pointer read will occur at runtime, implying the abort of the program.
The argument variable iEdgeList is not tested before use.
The following code will report a LCAVMCBU error:
long CATTopBasicTools::GetTangentDirection(..., CATLISTP(CATEdge) *iEdgeList ...) { if ( iEdgeList-> Size() == 1) { ... } ... } |
The correct code is:
long CATTopBasicTools::GetTangentDirection(..., CATLISTP(CATEdge) *iEdgeList ...) { if (! iEdgeList) return 0; // for example if ( iEdgeList-> Size() == 1) { ... } ... } |
[Top]
LCLVMCBU2 stands for LifeCycle: Local Variable Missing Check Before Use type 2.
An error of type LCLVMCBU2 is reported when:
If the assigning method returned a null pointer, a null pointer read will occur at runtime, leading to the abort of the program.
The local variable is not tested.
The following code will report a LCLVMCBU2 Error:
... CATFcaElementIParamsExt* element= ...; // Retrieve element if( element ) { CATIParmPublisher * ipDescendants = NULL; element->QueryInterface( CATIParmPublisher::ClassId(), (void**) &ipDescendants ); CATListValCATISpecObject_var ihSpec_parameters; ipDescendants-> GetAllChildren(CATIAParameter::ClassName(), ihSpec_parameters); ipDescendants-> Release(); ipDescendants= NULL; ... } ... |
The correct code is:
... CATFcaElementIParamsExt* element= ...; // Retrieve element if( element ) { CATIParmPublisher * ipDescendants = NULL; HRESULT hr= element->QueryInterface( CATIParmPublisher::ClassId(), (void**) &ipDescendants ); if( SUCCEEDED( hr ) ) { CATListValCATISpecObject_var ihSpec_parameters; ipDescendants-> GetAllChildren(CATIAParameter::ClassName(), ihSpec_parameters); ipDescendants-> Release(); ipDescendants= NULL; } ... } ... |
LCDMMCBU2 stands for LifeCycle: Data Member Missing Check Before Use type 2.
An error of type LCDMMCBU2 is reported when:
If the assigning method returned a null pointer, a null pointer read will occur at runtime, implying the abort of the program.
The data member is not tested.
Let's take the following class:
class CATPrtCreateHoleCom { ... CATINewHole* _pHole; HRESULT CreateHole(void*); ...; }; |
The following code will report a LCDMMCBU2 Error:
... HRESULT CATPrtCreateHoleCom::CreateHole (void *) { ... CATISpecObject_var hHole= ...; // Retrieve hHole hHole-> QueryInterface(CATINewHole::ClassId(), (void **)&_pHole); CATISpecObject_var hSpecLimit; _pHole-> GetLimit(hSpecLimit); _pHole->Release(); _pHole= NULL; ... // Use hSpecLimit } ... |
The correct code is:
... HRESULT CATPrtCreateHoleCom::CreateHole (void *) { ... CATISpecObject_var hHole= ...; // Retrieve hHole HRESULT hr= hHole-> QueryInterface(CATINewHole::ClassId(), (void **)&_pHole); CATISpecObject_var hSpecLimit; if( SUCCEEDED( hr ) ) { _pHole-> GetLimit(hSpecLimit); _pHole->Release(); _pHole= NULL; } ... // Use hSpecLimit } ... |
LCAVMCBU2 stands for LifeCycle: Argument Variable Missing Check Before Use type 2.
An error of type LCAVMCBU2 is reported when:
If the assigning method returned a null pointer, a null pointer read will occur at runtime, implying the abort of the program.
The argument variable is not tested.
The following code will report a LCAVMCBU2 Error:
... HRESULT CATSPPPhysicalActivityFlowMgt::AddControlInput(CATIPcsProductIO*& oCIO, const CATBaseUnknown_var & iItem) { HRESULT rc= E_FAIL; CATISpecObject* pCISO =... ; // Retrieve pCISO if ( pCISO ) { rc = pCISO-> QueryInterface(IID_CATIPcsProductIO,(void**)&oCIO); oCIO -> SetItem(iItem); } return rc; } ... |
The correct code is:
... HRESULT CATSPPPhysicalActivityFlowMgt::AddControlInput(CATIPcsProductIO*& oCIO, const CATBaseUnknown_var & iItem) { HRESULT rc= E_FAIL; CATISpecObject* pCISO =... ; // Retrieve pCISO if ( pCISO ) { rc = pCISO-> QueryInterface(IID_CATIPcsProductIO,(void**)&oCIO); if( SUCCEEDED( rc ) ) { oCIO -> SetItem(iItem); } } return rc; } .... |
[Top]
For a more complete description of Setting Files, see [3].
This section is located in: SettingsSet > OptionLists > LifeCycle_OptionLists
This section contains a list of ClassName. Every instance of class contained in this list will be excluded from all checks of type Null Pointers Part 2.
Be careful:
Example:
ClassName CATDialog
This means that no instance of class CATDialog (or any inherited class) will generate an error of type Null Pointers Part 2.
This section is located in: SettingsSet > OptionLists > LifeCycle_OptionLists
This section contains a list of Call. Each Call describes a method or function which can return a null pointer:
Be careful:
Example 1:
ClassName CATBaseUnknown MethodOrFunctionSign QueryInterface
This means that the method QueryInterface of the class CATBaseUnknown can return a null pointer.
This section is located in: SettingsSet > OptionLists > LifeCycle_OptionLists
This section contains a list of CallDeclaration. Each Call describes a method or function which cannot return a null pointer:
Example 1:
FrameworkName System ClassName CATBaseUnknown MethodOrFunctionSign GetImpl
This means that the method GetImpl of the class CATBaseUnknown defined in framework System never returns a null pointer.
[Top]
All checks included in Pointers Null Part 2 insure that no null pointer read will occur at runtime.
[Top]
[1] | CAA V5 C++ Coding Rules |
[2] | Null Pointers Part 2 Checks |
[3] | Setting Files |
[Top] |
Version: 1 [May 2001] | Document created |
[Top] |
Copyright © 2000, Dassault Systèmes. All rights reserved.