
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>
77 lines
2.2 KiB
Plaintext
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[]
|