exponenta event banner

Недопустимые операции C++

Произошли недопустимые операции C++

Описание

Эти проверки операций с кодом C++ определяют, являются ли операции допустимыми. Проверки ищут диапазон недопустимых вариантов поведения:

  • Размер массива не является строго положительным.

  • typeid оператор отменяет ссылки на NULL указатель.

  • dynamic_cast оператор выполняет недопустимое приведение.

  • (C++ 11 и более) Число предложений инициализатора массива превышает число инициализируемых элементов массива.

  • (C++ 11 и далее) Аргумент указателя на оператор placement new указывает на недостаточно памяти.

Примеры

развернуть все

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);
  }
}

В этом примере аргумент n в конструктор License::License подразделяется на две категории:

  • n = 0: Когда new использует этот аргумент, недопустимые операции C++ приводят к ошибке.

  • n > 0: Когда new оператор использует этот аргумент, недопустимые операции C++ имеют зеленый цвет.

Объединяя две категории аргументов, определенные операции Invalid C++ приводят к оранжевой ошибке в new оператор.

Чтобы увидеть эту проблему, включите параметр 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.";
  }

}

В этом примере Shape* указатель shapePtr возвращено getShapePtr() функция может быть NULL. Потому что, возможно, NULL- ценный shapePtr используется с typeid оператор, проверка недопустимых операций C++ оранжевого цвета.

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
}

В этом примере недопустимые операции C++ для dynamic_cast оператор:

  • Зеленый, когда указатель ptrBase что оператор бросает на Derived уже указывает на Derived объект.

  • Красный, когда указатель ptrBase что оператор бросает на Derived указывает на Base объект.

    Красные проверки обычно останавливают проверку в той же области, что и проверка. Однако после красного цвета недопустимые операции C++ для dynamic_cast операция с использованием указателей, проверка продолжается. Программное обеспечение предполагает, что dynamic_cast оператор возвращает NULL указатель.

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);
}

В этом примере недопустимые операции C++ для dynamic_cast оператор:

  • Зеленый, когда ссылка refBase1 что оператор бросает на Derived& уже ссылается на Derived объект.

  • Красный, когда ссылка refBase2 что оператор бросает на Derived& ссылается на Base объект.

    После красного Недопустимые операции C++ на dynamic_cast при работе с указателями программа не проверяет код в той же области, что и проверка. Например, программное обеспечение не выполняет проверку утверждения пользователя на assert заявление.

#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;
}

В этом примере проверка операций Invalid C++ определяет, соответствует ли количество предложений инициализатора количеству инициализируемых элементов.

В первом вызове allocate_constsсписок инициализации содержит три элемента для инициализации массива третьего размера. Проверка недопустимых операций C++ на new оператор зеленый. Во втором вызове список инициализации имеет два элемента, но инициализирует массив размера один. Проверка на new оператор - красный.

#include <new>

class aClass {
  virtual void func();  
};

void allocateNObjects(unsigned int n) {
    char* location = new char[sizeof(aClass)];
    aClass* objectLocation = new(location) aClass[n];  
}

В этом примере объем памяти равен единице aClass объект связан с указателем location. Однако в зависимости от аргумента функции n при использовании размещения может быть назначено несколько объектов new оператор. Указатель location возможно, недостаточно памяти для выделенных объектов.

Проверить информацию

Группа: C++
Язык: C++
Акроним: CPP