Fred Tingaud 22b4470f2a
Modify CFamily rules: CPP-4080 Refresh and standardize CppCoreGuidelines references (#3514)
Update all links to C++ Core Guidelines to `e49158a`.

Refresh done using the following script and some manual edits:
db76e34e74/personal/fred-tingaud/rspec/refresh-cppcoreguidelines.py

When re-using this script, be mindful that:
 - it does not cover `shared_content`
 - it does not properly escape inline code in links (e.g., "[=]" or "`mutex`es")
 - it does not change `C++` to `{cpp}` in link titles.

Co-authored-by: Marco Borgeaud <marco.borgeaud@sonarsource.com>
2023-12-20 10:08:18 +01:00

77 lines
2.2 KiB
Plaintext

== Why is this an issue?
A base class and its derived class often differ in size.
Accessing an array of a derived class through a pointer to the base class leads to wrong pointer arithmetic and can then corrupt memory.
=== Noncompliant code example
[source,cpp]
----
struct Base { /*...*/};
struct Derived : public Base { /*...*/};
void f(Base const &b);
int main() {
const size_t size = 4;
Derived derivedArray[size];
Base* basePointer = derivedArray; // Noncompliant
f(basePointer[2]); // The arithmetic will use the size of Base, not the size of Derived, and point to a random byte in the array
}
----
If you need to do a cast from derived to base in an array, do it element by element.
=== Compliant solution
[source,cpp]
----
#include<iostream>
using namespace std;
struct Base {
int iBase = 0;
};
struct Derived : public Base {
int iDerived = 0;
};
int main() {
const size_t size = 4;
Derived derivedArray[size];
for(int i=0; i<size; ++i) {
derivedArray[i].iBase = i; // store : 0 1 2 3
derivedArray[i].iDerived = i*1000;
}
for(int i=0; i<size; ++i) {
cout<<"derivedArray["<<i<<"].iBase="<<derivedArray[i].iBase<<endl; // display : 0 1 2 3
cout<<"base of derivedArray["<<i<<"].iBase="<<static_cast<Base*>(derivedArray+i)->iBase<<endl; // display : 0 1 2 3
}
return 0;
}
----
== Resources
* {cpp} Core Guidelines - https://github.com/isocpp/CppCoreGuidelines/blob/e49158a/CppCoreGuidelines.md#c152-never-assign-a-pointer-to-an-array-of-derived-class-objects-to-a-pointer-to-its-base[C.152: Never assign a pointer to an array of derived class objects to a pointer to its base]
ifdef::env-github,rspecator-view[]
'''
== Comments And Links
(visible only on this page)
=== relates to: S5410
=== on 25 Oct 2019, 16:27:29 Geoffray Adde wrote:
First, we try a much stronger, constraining and simpler version of the rule: no array (C-style, std::array and std::vector) of publicly derived class.
=== on 18 Dec 2019, 17:55:05 Loïc Joly wrote:
If you want to try the stronger version, why not directly document it? I think it might have value on its own, as a code smell... And I would also prevent arrays of base classes.
endif::env-github,rspecator-view[]