2016-10-07 7 views
3

Consultez le code suivant:Accès mémoire non aligné: le comportement est-il défini ou non?

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

Est-ce considéré comme un code valide, ou est-il fuite de mémoire/comportement non défini? Je demande, parce que grâce à:

*u = 42; 
*uc = 42; 

nous accédons octets qui ne devrait pas être accessible par le programme (je suppose).

+0

Recherchez un mot-clé non standard pris en charge par votre compilateur, quelque chose ressemblant '__packed' ou' __unaligned'. –

+0

Vous modifiez la mémoire à laquelle vous ne devriez pas avoir accès. Donc, je ne pense pas que cela soit important que ce soit sur une frontière de mot. –

Répondre

4

*u = 42; provoque un comportement indéfini en violant la règle d'alias strict. *u est une lvalue de type unsigned long long, et la règle stricte d'aliasing indique que cela peut seulement être utilisé pour accéder à des objets (qui existent déjà) et avoir le type long long ou unsigned long long. Cependant, votre code l'utilise pour accéder à un tableau de char.

C++ n'a pas de règle spécifique pour les accès alignés (contrairement à C). En effet, en C++, il est impossible d'écrire du code qui exécuterait un accès non alignés sans provoquer un comportement non défini en raison de l'une des choses suivantes:

  • ne respecte pas la règle stricte de aliasing.
  • accéder à la mémoire là où aucun objet n'existe.
  • en fournissant une adresse non alignée à l'emplacement-nouveau.