Нераспределенный доступ к памяти: это определенное поведение или нет?

Рассмотрим следующий код:

#include <iostream>

int main()
{
    char* c = new char('a');
    char ac[4] = {'a', 'b', 'c', 'd'};
    unsigned long long int* u = reinterpret_cast<unsigned long long int*>(c);
    unsigned long long int* uc = reinterpret_cast<unsigned long long int*>(&ac[3]);
    *u = 42;
    *uc = 42;
    std::cout<<*u<<" "<<*uc<<std::endl;
}

Это считается допустимым кодом, или это утечка памяти / неопределенное поведение? Я спрашиваю, потому что через:

*u = 42;
*uc = 42;

мы получаем доступ к байтам, которые не должны быть доступны для программы (я полагаю).

1 ответ

Решение

*u = 42; вызывает неопределенное поведение, нарушая строгое правило алиасинга. *u является lvalue типа unsigned long longи строгое правило псевдонимов говорит, что это может использоваться только для доступа к объектам (которые уже существуют) и имеют тип long long или же unsigned long long, Однако ваш код использует его для доступа к массиву char,

В C++ нет специального правила для выровненного доступа (в отличие от C). Это связано с тем, что в C++ невозможно написать код, который выполнял бы невыровненный доступ, не вызывая неопределенного поведения, из-за одной из следующих вещей:

  • нарушая строгое правило алиасинга.
  • доступ к памяти, где нет объекта.
  • предоставление невыровненного адреса для размещения новых.
Другие вопросы по тегам