Битовые операции и операции, которые принимают представление данных в памяти, не должны выполняться на объектах
Битовые операции и операции, которые принимают представление данных в памяти, не должны выполняться на объектах.
На C++ объектное представление в памяти может включать:
Элементы данных объявляются с различными правами доступа
Элементы данных битового поля
Дополнение байтов между элементами данных
Дополнение байтов в конце элементов данных
Указатели на vtable, чтобы поддерживать виртуальные функции
Расположение этих различных частей объекта в памяти является зависимым среды. Кроме того, статические элементы данных или функциональные члены объекта хранятся в отдельном физическом месте в памяти. Когда вы выполняете битовую операцию на объекте путем принятия определенного расположения данных в памяти, вы можете непреднамеренно принять неправильно, и биты доступа не являются частью представления значения объекта. Доступ к этим битам может привести к неопределенному поведению.
Рассмотрите этот класс, который содержит виртуальную функцию:
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
хранится в блоке памяти, блок содержит указатель на виртуальную таблицу в дополнение к переменным Obj::value
и Obj::dvalue
. Размер этого указателя или его местоположения в памяти может зависеть от среды. В main()
, std::memset()
попытки установить значение Obj::value
путем предположения, что:
Obj::value
первый блок в представлении памяти Obj
.
Obj::value
представлен на 2 байта в памяти.
Поскольку эти предположения обычно не правильны, с помощью std::memset()
может привести к неопределенному поведению. Например, если вы непреднамеренно изменяете указатель на виртуальную таблицу, вызывая foo()
может вызвать неожиданную функцию.
Представление класса и структур в памяти зависимо средой и может содержать дополнительные байты вместе с представлением значения. Доверие представлению данных объекта выполнить битовые операции может привести к изменению битов, которые не являются частью представления значения, ведя к неопределенному поведению. Избегайте операций, которые принимают определенное представление объекта в памяти, чтобы получить доступ к ее битам. Чтобы выполнить операции на классе, используйте выделенные функции членства, перегруженные операторы или мутаторы.
Функции C, что биты памяти доступов к доступу включают std::memset()
, std::memcpy()
, std::memmove()
, std::strcpy()
, std::memcmp()
, std::strcmp()
. Polyspace® отмечает оператор когда:
Вы используете функции C, чтобы инициализировать или скопировать, инициализируют нетривиальные объекты
Вы используете функции C, чтобы сравнить нестандартные объекты размещения
Вы используете функции C на любых объектах, которые содержат дополнительные данные
Операторы, содержащие несовместимые операции, отмечаются, и подсвечены соответствующие объявления класса. Для определений тривиальных и стандартных классов макета см. Стандарт C++, [класс], абзацы 6 и 7 соответственно.
Как исключение, Polyspace не отмечает операции, которые используют функции C, чтобы получить доступ к битам памяти тривиальных и стандартных объектов размещения без дополнения данных. Несмотря на то, что использование битовой операции на тривиальных и стандартных классах макета без дополнения данных выполняет это правило, это не хорошая практика. Вместо этого используйте выделенную функцию членства, перегруженные операторы или мутаторы.
Если вы ожидаете нарушение правила, но не видите его, обратитесь к Кодированию Стандартных Нарушений, Не Отображенных.
Группа: Специальные функции членства |
Категория: Необходимый, Частично автоматизированный |