Main Content

Invalid C++ specific operations

C++ specific invalid operations occur

Description

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.

Examples

expand all

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.

To 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.

class 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.

class 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.

#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.

Check Information

Group: C++
Language: C++
Acronym: CPP