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

В следующем коде я определяю структуру 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 и фактический размер объекта не совпадают?

1 Ответ

5 голосов
/ 16 апреля 2020

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

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

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

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

Избавиться от чего-либо - это не то же самое, что «работать».

...