В следующем коде я определяю структуру header из 9 байтов, и она выравнивается по размеру 16 байтов. Затем я динамически выделяю 9 байтов из кучи и назначаю их указателю header .

struct header                 
{
     uint8_t chunk_id;               
     long int format;                 
};

int main()
{   
    std::cout << "sizeof(header) " << sizeof(header) << '\n';

    auto head = (header*)malloc(9);
    head->chunk_id =3;
    head->format=5;    
    std::cout << (int)head->chunk_id << " " << head->format << '\n' << sizeof(*head);

    free(head);
    return 0;
}

Выход:

sizeof(header) 16
3 5
16

Как оказалось, sizeof по-прежнему сообщает, что этот объект имеет размер 16 байт (хотя это 9). Я думаю, это просто смотрит на определение структуры. Но как все работает (включая оператор '->'), когда размер sizeof и фактический размер объекта не совпадают?

3
Nikita128 16 Апр 2020 в 08:16

1 ответ

Лучший ответ

Но как все работает (включая оператор '->'), когда размер sizeof и фактический размер объекта не совпадают?

Просто: это не так. Вы солгали реализации и поэтому применили неопределенное поведение.

Во-первых, вы никогда не создавали объект header в памяти; вы просто помещаете часть памяти в этот объект header. Итак, у вас есть указатель, который не указывает на объект, но вы делаете вид, что он указывает.

Во-вторых, даже если вы попытались правильно создать объект header в этой памяти (или, альтернативно, вы используете неявные правила создания C ++ 20), определение malloc не требует, чтобы он возвращал достаточно пространство для хранения большего количества байтов, чем вы указали. Поскольку sizeof(header) равно 16, а вы запросили только 9, ваш код будет работать только с реализациями malloc, которые сделают доступными 16 или более байтов для вашего кода, когда вы запросите 9 (на самом деле это не редкость). В противном случае вы создаете объект, который занимает больше памяти, чем доступно через этот указатель, который также является UB.

Уйти от чего-либо - это не то же самое, что «работать».

5
Nicol Bolas 16 Апр 2020 в 05:27