Our website uses cookies to enhance your browsing experience.
Accept
to the top
close form

Fill out the form in 2 simple steps below:

Your contact information:

Step 1
Congratulations! This is your promo code!

Desired license type:

Step 2
Team license
Enterprise license
** By clicking this button you agree to our Privacy Policy statement
close form
Request our prices
New License
License Renewal
--Select currency--
USD
EUR
* By clicking this button you agree to our Privacy Policy statement

close form
Free PVS‑Studio license for Microsoft MVP specialists
* By clicking this button you agree to our Privacy Policy statement

close form
To get the licence for your open-source project, please fill out this form
* By clicking this button you agree to our Privacy Policy statement

close form
I am interested to try it on the platforms:
* By clicking this button you agree to our Privacy Policy statement

close form
check circle
Message submitted.

Your message has been sent. We will email you at


If you do not see the email in your inbox, please check if it is filtered to one of the following folders:

  • Promotion
  • Updates
  • Spam

Webinar: Evaluation - 05.12

>
>
>
V777. Dangerous widening type conversio…
menu mobile close menu
Analyzer diagnostics
General Analysis (C++)
General Analysis (C#)
General Analysis (Java)
Micro-Optimizations (C++)
Diagnosis of 64-bit errors (Viva64, C++)
Customer specific requests (C++)
MISRA errors
AUTOSAR errors
OWASP errors (C++)
OWASP errors (C#)
Problems related to code analyzer
Additional information
toggle menu Contents

V777. Dangerous widening type conversion from an array of derived-class objects to a base-class pointer.

Dec 09 2016

The analyzer detected a possible error that has to do with accessing an array consisting of objects of a derived class by using a pointer to the base class. Attempting to access an element with a nonzero index through a pointer to the base class will result in an error.

Consider the following example:

class Base
{
  int buf[10];

public:
  virtual void Foo() { ... }
  virtual ~Base() { }
};

class Derived : public Base
{
  char buf[10];

public:
  virtual void Foo() override { ... }
  virtual ~Derived() { }
};

....
size_t n = 5;
Base *ptr = new Derived[n];   // <=
....
for (size_t i = 0; i < n; ++i)
  (ptr + i)->Foo();
....

This code uses a base class "Base" and a class derived from it, "Derived". Each object of these classes occupies 48 and 64 bytes respectively (due to class alignment on an 8-byte boundary; the compiler used is MSVC, 64-bit). When "i >= 1", the pointer has to be offset by "i * 64" bytes each time when accessing an element with a nonzero index, but since the array is accessed through a pointer to the "Base" base class, the offset will actually be "i * 48" bytes.

This is how the pointer's offset was meant to be computed:

V777/image1.png

This is how it is actually computed:

V777/image2.png

In fact, the program starts handling objects containing random data.

This is the fixed code:

....
size_t n = 5;
Derived *ptr = new Derived[n];   // <=
....
for (size_t i = 0; i < n; ++i)
  (ptr + i)->Foo();
....

It is also a mistake to cast a pointer that refers to the pointer to the derived class to a pointer that refers to the pointer to the base class:

....
Derived arr[3];
Derived *pDerived = arr;
Class5 **ppDerived = &pDerived;
....
Base **ppBase = (Derived**)ppDerived; // <=
....

To ensure that an array of derived-class objects is properly stored in a polymorphic way, the objects have to be arranged as shown below:

V777/image3.png

This is what the correct version of this code should look like:

....
size_t n = 5;
Base **ppBase = new Base*[n]; // <=

for (size_t i = 0; i < n; ++i)
  ppBase[i] = new Derived();
....

If you want to emphasize that you are going to handle one object only, use the following code:

....
Derived *derived = new Derived[n];
Base *base = &derived[i];
....

This code is considered safe by the analyzer and does not trigger a warning.

It is also considered a valid practice to use such a pointer to access an array consisting of a single object of the derived class.

....
Derived arr[1];
Derived *new_arr = new Derived[1];
Derived *malloc_arr = static_cast<Base*>(malloc(sizeof(Derived)));
....
Base *base = arr;
base = new_arr;
base = malloc_arr;
....

Note. If the base and derived classes are of the same size, it is valid to access an array of derived-class objects though a pointer to the base class. However, this practice is still not recommended for use.

This diagnostic is classified as: