C++ specific invalid operations occur
These checks on C++ code operations determine whether the operations are valid. The checks look for a range of invalid behaviors:
Array size is not strictly positive.
typeid operator dereferences a NULL pointer.
dynamic_cast operator performs
an invalid cast.
(C++11 and beyond) The number of array initializer clauses exceeds the number of array elements to initialize.
(C++11 and beyond) The pointer argument to a placement new operator does not point to enough memory.
class License {
protected:
int numberOfUsers;
char (*userList)[20];
int *licenseList;
public:
License(int numberOfLicenses);
void initializeList();
char* getUser(int);
int getLicense(int);
};
License::License(int numberOfLicenses) : numberOfUsers(numberOfLicenses) {
userList = new char [numberOfUsers][20];
licenseList = new int [numberOfUsers];
initializeList();
}
int getNumberOfLicenses();
int getIndexForSearch();
void main() {
int n = getNumberOfLicenses();
if(n >= 0 && n <= 100) {
License myFirm(n);
int index = getIndexForSearch();
myFirm.getUser(index);
myFirm.getLicense(index);
}
}In this example, the argument n to the constructor License::License falls
into two categories:
n = 0: When the new operator
uses this argument, the Invalid C++ specific operations produce
an error.
n > 0: When the new operator
uses this argument, the Invalid C++ specific operations is
green.
Combining the two categories of arguments, the Invalid
C++ specific operations produce an orange error on the new operator.
typeid Operator Dereferencing NULL PointerTo see this issue, enable the option Consider environment pointers as unsafe (-stubbed-pointers-are-unsafe).
#include <iostream>
#include <typeinfo>
#define PI 3.142
class Shape {
public:
Shape();
virtual void setVal(double) = 0;
virtual double area() = 0;
};
class Circle: public Shape {
double radius;
public:
Circle(double radiusVal):Shape() {
setVal(radiusVal);
}
void setVal(double radiusVal) {
radius = radiusVal;
}
double area() {
return (PI * radius * radius);
}
};
Shape* getShapePtr();
void main() {
Shape* shapePtr = getShapePtr();
double val;
if(typeid(*shapePtr)==typeid(Circle)) {
std::cout<<"Enter radius:";
std::cin>>val;
shapePtr->setVal(val);
std::cout<<"Area of circle = "<<shapePtr->area();
}
else {
std::cout<<"Shape is not a circle.";
}
}In this example, the Shape* pointer shapePtr returned by
getShapePtr() function can be NULL. Because a
possibly NULL-valued shapePtr is used with the
typeid operator, the Invalid C++ specific
operations check is orange.
dynamic_cast on Pointersclass Base {
public :
virtual void func() ;
};
class Derived : public Base {
};
Base* returnObj(int flag) {
if(flag==0)
return new Derived;
else
return new Base;
}
int main() {
Base * ptrBase;
Derived * ptrDerived;
ptrBase = returnObj(0) ;
ptrDerived = dynamic_cast<Derived*>(ptrBase); //Correct dynamic cast
assert(ptrDerived != 0); //Returned pointer is not null
ptrBase = returnObj(1);
ptrDerived = dynamic_cast<Derived*>(ptrBase); //Incorrect dynamic cast
// Verification continues despite red
assert(ptrDerived == 0); //Returned pointer is null
}
In this example, the Invalid C++ specific operations on
the dynamic_cast operator are:
Green, when the pointer ptrBase that
the operator casts to Derived is already pointing
to a Derived object.
Red, when the pointer ptrBase that
the operator casts to Derived is pointing to a Base object.
Red checks typically stop the verification in the same scope
as the check. However, after red Invalid C++ specific operations on dynamic_cast operation
involving pointers, the verification continues. The software assumes
that the dynamic_cast operator returns a NULL pointer.
dynamic_cast on Referencesclass Base {
public :
virtual void func() ;
};
class Derived : public Base {
};
Base& returnObj(int flag) {
if(flag==0)
return *(new Derived);
else
return *(new Base);
}
int main() {
Base & refBase1 = returnObj(0);
Derived & refDerived1 = dynamic_cast<Derived&>(refBase1); //Correct dynamic cast;
Base & refBase2 = returnObj(1);
Derived & refDerived2 = dynamic_cast<Derived&>(refBase2); //Incorrect dynamic cast
// Analysis stops
assert(1);
}In this example, the Invalid C++ specific operations on
the dynamic_cast operator are:
Green, when the reference refBase1 that
the operator casts to Derived& is already referring
to a Derived object.
Red, when the reference refBase2 that
the operator casts to Derived& is referring
to a Base object.
After red Invalid C++ specific operations on dynamic_cast operation
involving pointers, the software does not verify the code in the same
scope as the check. For instance, the software does not perform the User
assertion check on the assert statement.
#include <stdio.h>
int* arr_const;
void allocate_consts(int size) {
if(size>1)
arr_const = new int[size]{0,1,2};
else if(size==1)
arr_const = new int[size]{0,1};
else
printf("Nonpositive array size!");
}
int main() {
allocate_consts(3);
allocate_consts(1);
return 0;
}
In this example, the Invalid C++ specific operations check determines if the number of initializer clauses match the number of elements to initialize.
In the first call to allocate_consts, the initialization list has
three elements to initialize an array of size three. The Invalid C++ specific
operations check on the new operator is green. In the second
call, the initialization list has two elements but initializes an array of size one. The
check on the new operator is red.
new Operator Does Not Point to Enough Memory#include <new>
class aClass {
virtual void func();
};
void allocateNObjects(unsigned int n) {
char* location = new char[sizeof(aClass)];
aClass* objectLocation = new(location) aClass[n];
}
In this example, memory equal to the size of one aClass object is
associated with the pointer location. However, depending on the function
argument n more than one object can be allocated when using the placement
new operator. The pointer location might not have
enough memory for the objects allocated.
| Group: C++ |
| Language: C++ |
| Acronym: CPP |