AUTOSAR C++14 Rule A12-0-2
Bitwise operations and operations that assume data representation in memory shall not be performed on objects
Since R2020b
Description
Rule Definition
Bitwise operations and operations that assume data representation in memory shall not be performed on objects.
Rationale
In C++, object representation in memory might include:
Data members declared with different access privileges
Bit-field data members
Padding bytes between data members
Padding bytes at the end of data members
Pointers to the vtable to support virtual functions
The arrangement of these different parts of an object in memory is environment dependent. In addition, static data members or function members of an object are stored in a separate physical location in memory. When you perform bitwise operation on an object by assuming certain arrangement of data in memory, you might inadvertently assume incorrectly, and access bits are not part of the value representation of the object. Accessing these bits can lead to undefined behavior.
Consider this class that contains a virtual function:
class notPOD{ public: virtual void foo(); int value; protected: double dvalue; }; //... int main(){ notPOD Obj; std::memset(&Obj, 57, 2); // attempts to set Obj::value to 57 }
Obj
is stored in a memory block, the block contains a pointer to the
virtual table in addition to the variables Obj::value
and
Obj::dvalue
. The size of this pointer or its location in memory can
depend on the environment. In main()
, std::memset()
attempts to set the value of Obj::value
by assuming that:
Obj::value
is the first block in the memory representation ofObj
.Obj::value
is represented by 2 bytes in the memory.
Because these assumptions are generally not correct, using
std::memset()
can lead to undefined behavior. For instance, if you
inadvertently modify the pointer to virtual table, calling foo()
can
invoke an unexpected function.
The representation of class and structures in memory is environment-dependent and can contain additional bytes alongside the value representation. Relying on the data representation of an object to perform bitwise operations can result in modifying bits that are not part of the value representation, leading to undefined behavior. Avoid operations that assume a certain representation of an object in memory to access its bits. To perform operations on a class, use dedicated member functions, overloaded operators, or mutators.
Polyspace Implementation
The C functions that access accesses memory bits includes
std::memset()
, std::memcpy()
,
std::memmove()
, std::strcpy()
,
std::memcmp()
, std::strcmp()
. Polyspace® flags a statement when:
You use the C functions to initialize or copy initialize nontrivial objects
You use the C functions to compare nonstandard layout objects
You use the C functions on any objects that contain padding data
The statements containing the noncompliant operations are flagged and relevant class declarations are highlighted. For definitions of trivial and standard layout classes, see the C++ Standard, [class], paragraphs 6 and 7 respectively.
As an exception, Polyspace does not flag operations that use the C functions to access the memory bits of trivial and standard layout objects with no padding data. Although using bitwise operation on trivial and standard layout classes with no padding data complies with this rule, it is not a good practice. Instead, use dedicated member function, overloaded operators, or mutators.
Troubleshooting
If you expect a rule violation but Polyspace does not report it, see Diagnose Why Coding Standard Violations Do Not Appear as Expected.
Examples
Check Information
Group: Special member functions |
Category: Required, Partially automated |
Version History
Introduced in R2020b