Cette question suit cette question précédente au sujet de la definedness d' memcpy(0, 0, 0)
, qui a été établi de façon concluante à un comportement indéfini.
Le site question, la réponse repose sur le contenu de C11 de la clause 7.1.4:1
Chacun des énoncés suivants s'applique à moins d'indication contraire dans la description détaillée qui suit: Si un argument à une fonction a une valeur non valide (par exemple une valeur en dehors du domaine de la fonction, ou un pointeur en dehors de l'espace d'adressage du programme, ou un pointeur null, [...]) [...] le comportement est indéfini. [...]
La fonction standard memcpy()
attend des pointeurs vers void
et const void
, comme suit:
void *memcpy(void * restrict s1, const void * restrict s2, size_t n);
La question vaut la peine de demander à tous les uniquement parce qu'il y a deux notions de "validité" des pointeurs dans la norme: il y a les pointeurs qui peuvent valablement être obtenus par le biais de l'arithmétique de pointeur et peut valablement être comparé avec <
, >
pour les autres pointeurs à l'intérieur du même objet. Et il y a des pointeurs qui sont valides pour un déréférencement. La première classe comprend "un passé" pointeurs comme &a + 1
et &b + 1
dans l'extrait suivant, alors que la seconde classe ne comprend pas ces comme valide.
char a;
const char b = '7';
memcpy(&a + 1, &b + 1, 0);
Si l'extrait ci-dessus sera considérée comme comportement défini, à la lumière du fait que les arguments de l' memcpy()
sont typés comme des indicateurs d' void
de toute façon, la question de leur validité ne peut pas être sur déréférencement les. Ou doit - &a + 1
et &b + 1
être considéré comme "en dehors de l'espace d'adressage du programme"?
C'est important pour moi parce que je suis dans le processus de formalisation des effets de la norme C fonctions. J'avais écrit une pré-condition de l' memcpy()
comme requires \valid(s1+(0 .. n-1));
,jusqu'à ce qu'il a été signalé à mon attention que la GCC 4.9 avait commencé de façon agressive optimiser la bibliothèque des appels de fonction au-delà de ce qui est exprimé dans la formule ci-dessus (en effet). La formule \valid(s1+(0 .. n-1))
dans ce langage de spécification est équivalent à true
lorsque n
est 0
, et ne capture pas le comportement non défini que GCC 4.9 s'appuie sur les optimiser.