2016-10-07 4 views
3

Рассмотрим следующий код:Unaligned доступ к памяти: определено ли это поведение или нет?

#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; 

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

+0

Ищите нестандартное ключевое слово, поддерживаемое вашим компилятором, что-то похожее на '__packed' или' __unaligned'. –

+0

Вы изменяете память, к которой у вас не должно быть доступа. Таким образом, я не думаю, что это важно, находится ли он на границе слова. –

ответ

4

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

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

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