Main Content

CERT C++: CTR56-CPP

Do not use pointer arithmetic on polymorphic objects

Since R2023a

Description

Rule Definition

Do not use pointer arithmetic on polymorphic objects.1

Polyspace Implementation

The rule checker checks for the issue Pointer Arithmetic on Polymorphic Object.

Examples

expand all

Issue

Pointer Arithmetic on Polymorphic Object occurs when you perform pointer arithmetic on a base class pointer pointing to a derived class object. Pointer arithmetic includes array subscripting.

Risk

Because the base class and derived class objects might not be the same size, when you attempt pointer arithmetic on a basic class type pointer and this pointer points to a derived class object, the result is undefined behavior.

Fix

Typically, the issue occurs when you try to access an array of derived class objects through a base class pointer. To fix this issue, iterate through an array of pointers to objects instead of an array of objects. Instead of a regular array, you can also use a standard template library container such as std::vector.

Example — Pointer Arithmetic with Polymorphic Objects

In this example, the Triangle class is derived from the Shape class. The function example() takes a Shape * pointer as first parameter. A pointer to an array of Triangle objects is passed to this parameter when the function is called from main(). The function body contains two instances of pointer arithmetic on the Shape * pointer:

  • In the initialization statement of the for loop, const Shape* end = exampleShape + count.

  • In the increment statement of the for loop, ++exampleShape.

#include <iostream>

class Shape
{
public:
	int height, width;
};

class Triangle : public Shape
{
public:
	double height, width;
};

void example(const Shape* exampleShape, std::size_t count)
{
	for (const Shape* end = exampleShape + count; exampleShape != end; ++exampleShape) //Noncompliant  	
      {
		std::cout << exampleShape->height << std::endl;
	}
}

int main()
{
	Triangle triforce[4] = {};
	example(triforce, 4);
}
Correction — Use an Array of Pointers

By switching the array of objects in the for loop for an array of pointers to objects, you are no longer performing the arithmetic on the objects, but rather on the pointers to the objects. This change avoids the undefined behavior with pointer arithmetic in the for loop.

#include <iostream>

class Shape
{
public:
	int height, width;
};

class Triangle : public Shape
{
public:
	double height, width;
};

void example(const Shape* const* exampleShape, std::size_t count)
{
	for (const Shape* const* end = exampleShape + count; exampleShape != end; ++exampleShape)
	{
		std::cout << (*exampleShape)->height << std::endl;
	}
}

void main()
{
	Shape* triforce[] = { new Triangle , new Triangle , new Triangle , new Triangle };
	example(triforce, 4);
}
Correction — Use an STL Container

Instead of an array of objects, the example uses the STL container std::vector and fills the vector with pointers to Triangle objects. example() takes two iterators as parameters, which are the beginning and end of the vector triforce. The for loop then cycles through the vector of pointers by performing arithmetic on the iterators instead of the polymorphic objects.

#include <iostream>
#include <vector>

class Shape
{
public:
	int height, width;
};

class Triangle : public Shape
{
public:
	double height, width;
};

template <typename Iter>

void example(Iter i, Iter e)
{
	for (; i != e; ++i)
	{
		std::cout << (*i)->height << std::endl;
	}
}

void main()
{
	std::vector<Shape*> triforce{ new Triangle , new Triangle , new Triangle , new Triangle };
	example(triforce.cbegin(), triforce.cend());

	for (auto v : triforce)
	{
		delete v;
	}
}

Check Information

Group: Rule 04. Containers (CTR)

Version History

Introduced in R2023a


1 This software has been created by MathWorks incorporating portions of: the “SEI CERT-C Website,” © 2017 Carnegie Mellon University, the SEI CERT-C++ Web site © 2017 Carnegie Mellon University, ”SEI CERT C Coding Standard – Rules for Developing safe, Reliable and Secure systems – 2016 Edition,” © 2016 Carnegie Mellon University, and “SEI CERT C++ Coding Standard – Rules for Developing safe, Reliable and Secure systems in C++ – 2016 Edition” © 2016 Carnegie Mellon University, with special permission from its Software Engineering Institute.

ANY MATERIAL OF CARNEGIE MELLON UNIVERSITY AND/OR ITS SOFTWARE ENGINEERING INSTITUTE CONTAINED HEREIN IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.

This software and associated documentation has not been reviewed nor is it endorsed by Carnegie Mellon University or its Software Engineering Institute.