Инициализация базовой части производной структуры / Неожиданная упаковка производных структурных полей для выравнивания разрыва базовой структуры - PullRequest
0 голосов
/ 07 октября 2018

Неожиданно было обнаружено, что clang ++ 7 позволяет себе плотно упаковать поля производной структуры (структура "B" с полем "B :: u16_gap" в примере ниже) в разрыв выравнивания базовой структуры (структура "А").Но функция "zero_init" в этом примере ожидает, что ее ввод будет "A" -объектом с неиспользованным промежутком выравнивания, поэтому он может быть перезаписан "memcpy".Эта функция «zero_init», конечно, перезаписывает любое значение поля «B :: u16_gap», когда применяется к объекту «B».

// compilation: clang++-7 -std=c++17 test.cpp
#include <cstdint>
#include <cstring>
#include <iostream>

struct A {
    std::uint32_t u32 = 0;
    std::uint16_t u16 = 0;
};

void zero_init(A& a) {
    static constexpr A zero = {};
    std::memcpy(&a, &zero, sizeof(A));
};

struct B: public A {
    std::uint16_t u16_gap = 0;
};

static_assert(sizeof(A) == 8);
static_assert(sizeof(B) == 8); // clang++-7 packs additional field "B::u16_gap" to the alignment gap of the A (for g++-7 it is not true)

int main() {
    B b;
    A& a = b;
    b.u16_gap = 123;
    zero_init(a);
    std::cout << b.u16_gap << std::endl; // writes "0" instead of expected "123"
}

Где находится плохо сформированная часть (отклонениеиз правил "хорошего поведения" стандарта C ++ 17) в этом коде?

1 Ответ

0 голосов
/ 07 октября 2018

Как показывает ваше статическое утверждение, размер A составляет 8 байт.Это означает, что ваш статический «нулевой» A-объект состоит из 8 байтов нулей.memcpy не знает о типах, поэтому вы копируете простые 8 байтов по адресу a и, таким образом, перезаписываете поле u16_gap, которое хранится в этих 8 байтах, как показано во втором утверждении.

Если вы хотите изменить это, вы можете просто скопировать 6 байтов, и это должно работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...