Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Comparaison entre pointeurs

25 réponses
Avatar
Taurre
Bonjour =E0 tous,

En lisant la norme C au sujet du comportement des op=E9rateurs de
comparaisons (<, <=3D, > et =3D>), j'ai vu que dans le cas o=F9 deux
pointeurs r=E9f=E9rencent des objets n'appartenant pas au m=EAme agr=E9gat,=
le
comportement est ind=E9termin=E9 (C11 [n1570] =A7 6.5.8 Relational operator=
s
al 5 pp 95-96).

Comparer l'adresse de deux objets ne faisant pas partie du m=EAme
agr=E9gat ne me para=EEt pas avoir beaucoup de sens, mais j'aurais voulu
savoir pourquoi il s'agit d'un comportement ind=E9termin=E9 ? Je veux
dire, techniquement, les pointeurs ne sont g=E9n=E9ralement rien de plus
que des entiers, aussi, en quoi leur comparaison serait-elle
probl=E9matique hormis les cas cit=E9s par la norme ? Existe-t-il des
architectures recourant =E0 des repr=E9sentations pouvant =EAtre
probl=E9matique en cas de comparaison ? Si oui, auriez-vous des
exemples ?

Merci d'avance pour vos r=E9ponses :)

10 réponses

1 2 3
Avatar
Erwan David
Taurre écrivait :


En lisant la norme C au sujet du comportement des opérateurs de
comparaisons (<, <=, > et =>), j'ai vu que dans le cas où deux
pointeurs référencent des objets n'appartenant pas au même agrégat, le
comportement est indéterminé (C11 [n1570] § 6.5.8 Relational operators
al 5 pp 95-96).

Comparer l'adresse de deux objets ne faisant pas partie du même
agrégat ne me paraît pas avoir beaucoup de sens, mais j'aurais voulu
savoir pourquoi il s'agit d'un comportement indéterminé ? Je veux
dire, techniquement, les pointeurs ne sont généralement rien de plus
que des entiers, aussi, en quoi leur comparaison serait-elle
problématique hormis les cas cités par la norme ? Existe-t-il des
architectures recourant à des représentations pouvant être
problématique en cas de comparaison ? Si oui, auriez-vous des
exemples ?

Merci d'avance pour vos réponses :)



Prends la mémoire segmentée des 8086, avec les overlapping tu pouvais
avoir des pointeurs différents pointant sur la même adresse ou des
pointeurs avec un poids fort plus élevé mais qui se trouvaient avant
dans la mémoire.

--
Le travail n'est pas une bonne chose. Si ça l'était,
les riches l'auraient accaparé
Avatar
Jean-Marc Bourguet
Erwan David writes:

Taurre écrivait :


En lisant la norme C au sujet du comportement des opérateurs de
comparaisons (<, <=, > et =>), j'ai vu que dans le cas où deux
pointeurs référencent des objets n'appartenant pas au même agrégat, le
comportement est indéterminé (C11 [n1570] § 6.5.8 Relational operators
al 5 pp 95-96).

Comparer l'adresse de deux objets ne faisant pas partie du même
agrégat ne me paraît pas avoir beaucoup de sens, mais j'aurais voulu
savoir pourquoi il s'agit d'un comportement indéterminé ? Je veux
dire, techniquement, les pointeurs ne sont généralement rien de plus
que des entiers, aussi, en quoi leur comparaison serait-elle
problématique hormis les cas cités par la norme ? Existe-t-il des
architectures recourant à des représentations pouvant être
problématique en cas de comparaison ? Si oui, auriez-vous des
exemples ?

Merci d'avance pour vos réponses :)



Prends la mémoire segmentée des 8086, avec les overlapping tu pouvais
avoir des pointeurs différents pointant sur la même adresse ou des
pointeurs avec un poids fort plus élevé mais qui se trouvaient avant
dans la mémoire.



On pouvait aussi décider de ne comparer que l'offset dans les modèles
mémoires ne permettant pas des objets de plus de 64K (quasiment tous). Donc
avoir p1 <= p2 && p1 >= p2 && p1 != p2 (offsets égaux, segments différents,
<= et >= comparent que les offsets, != compare offsets et segments).

A+
--
Jean-Marc
FAQ de fclc: http://www.levenez.com/lang/c/faq
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Avatar
Erwan David
Jean-Marc Bourguet écrivait :

Erwan David writes:

Taurre écrivait :


En lisant la norme C au sujet du comportement des opérateurs de
comparaisons (<, <=, > et =>), j'ai vu que dans le cas où deux
pointeurs référencent des objets n'appartenant pas au même agrégat, le
comportement est indéterminé (C11 [n1570] § 6.5.8 Relational operators
al 5 pp 95-96).

Comparer l'adresse de deux objets ne faisant pas partie du même
agrégat ne me paraît pas avoir beaucoup de sens, mais j'aurais voulu
savoir pourquoi il s'agit d'un comportement indéterminé ? Je veux
dire, techniquement, les pointeurs ne sont généralement rien de plus
que des entiers, aussi, en quoi leur comparaison serait-elle
problématique hormis les cas cités par la norme ? Existe-t-il des
architectures recourant à des représentations pouvant être
problématique en cas de comparaison ? Si oui, auriez-vous des
exemples ?

Merci d'avance pour vos réponses :)



Prends la mémoire segmentée des 8086, avec les overlapping tu pouvais
avoir des pointeurs différents pointant sur la même adresse ou des
pointeurs avec un poids fort plus élevé mais qui se trouvaient avant
dans la mémoire.



On pouvait aussi décider de ne comparer que l'offset dans les modèles
mémoires ne permettant pas des objets de plus de 64K (quasiment tous). Donc
avoir p1 <= p2 && p1 >= p2 && p1 != p2 (offsets égaux, segments différents,
<= et >= comparent que les offsets, != compare offsets et segments).




On pouvaiut, mais ce n'était pas obligatoire. Donc comportement indéfini
(par la norme). Une implémentation est alors censée indiquer ce qu'elle fait.

--
Le travail n'est pas une bonne chose. Si ça l'était,
les riches l'auraient accaparé
Avatar
espie
In article ,
Erwan David wrote:
Jean-Marc Bourguet écrivait :
On pouvait aussi décider de ne comparer que l'offset dans les modèles
mémoires ne permettant pas des objets de plus de 64K (quasiment tous). Donc
avoir p1 <= p2 && p1 >= p2 && p1 != p2 (offsets égaux, segments différents,
<= et >= comparent que les offsets, != compare offsets et segments).




On pouvaiut, mais ce n'était pas obligatoire. Donc comportement indéfini
(par la norme). Une implémentation est alors censée indiquer ce qu'elle fait.



Attention, de la maniere dont tu formules les choses, tu melanges
"undefined behavior" et "implementation defined defined", ce qui n'est
pas gentil pour les debutants qui nous lisent.

Une implementation "n'est PAS censee indiquer ce qu'elle fait" ! J'ai
reverifie ma norme, la comparaison entre pointeurs non correles est bien
une "undefined behavior"

Il peut donc se passer relativement n'importe quoi dans le cadre du C
standard.
Avatar
Erwan David
(Marc Espie) écrivait :

In article ,
Erwan David wrote:
Jean-Marc Bourguet écrivait :
On pouvait aussi décider de ne comparer que l'offset dans les modèles
mémoires ne permettant pas des objets de plus de 64K (quasiment tous). Donc
avoir p1 <= p2 && p1 >= p2 && p1 != p2 (offsets égaux, segments différents,
<= et >= comparent que les offsets, != compare offsets et segments).




On pouvaiut, mais ce n'était pas obligatoire. Donc comportement indéfini
(par la norme). Une implémentation est alors censée indiquer ce qu'elle fait.



Attention, de la maniere dont tu formules les choses, tu melanges
"undefined behavior" et "implementation defined defined", ce qui n'est
pas gentil pour les debutants qui nous lisent.

Une implementation "n'est PAS censee indiquer ce qu'elle fait" ! J'ai
reverifie ma norme, la comparaison entre pointeurs non correles est bien
une "undefined behavior"

Il peut donc se passer relativement n'importe quoi dans le cadre du C
standard.



Oui, mea culpa, j'ai effectivement mélangé les 2 notions. undefined
c'est undefined et ça peut faire n'importe quoi.

--
Le travail n'est pas une bonne chose. Si ça l'était,
les riches l'auraient accaparé
Avatar
Taurre
Merci pour vos réponses, j'y vois désormais plus clair à ce sujet :)
Il me reste cependant une petite question :

J'ai reverifie ma norme, la comparaison entre pointeurs non correles est bien
une "undefined behavior".
Il peut donc se passer relativement n'importe quoi dans le cadre du C sta ndard.



C'est en effet ce qui me perturbe. Que la mémoire soit ou non
segmentée, les pointeurs restent des entiers, les comparer ne doit
donc pas poser de problème. Existe-t-il des architectures où une telle
comparaison provoquerait une erreur (comme par exemple l'émission d'un
signal) ?
Avatar
Marc
Taurre wrote:

Bonjour à tous,

En lisant la norme C au sujet du comportement des opérateurs de
comparaisons (<, <=, > et =>), j'ai vu que dans le cas où deux
pointeurs référencent des objets n'appartenant pas au même agrégat, le
comportement est indéterminé (C11 [n1570] § 6.5.8 Relational operators
al 5 pp 95-96).



Une note pour meubler : C++, qui a le même opérateur < que le C, fournit
à côté std::less qui définit un ordre total sur les pointeurs (de même
type).
Avatar
Erwan David
Taurre écrivait :

Merci pour vos réponses, j'y vois désormais plus clair à ce sujet :)
Il me reste cependant une petite question :

J'ai reverifie ma norme, la comparaison entre pointeurs non correles est bien
une "undefined behavior".
Il peut donc se passer relativement n'importe quoi dans le cadre du C standard.



C'est en effet ce qui me perturbe. Que la mémoire soit ou non
segmentée, les pointeurs restent des entiers, les comparer ne doit
donc pas poser de problème. Existe-t-il des architectures où une telle
comparaison provoquerait une erreur (comme par exemple l'émission d'un
signal) ?



On peut imaginer des archis où la comparaison fasse intervenir une
différence et qu'une différence de pointeurs dans des aggrégats
différents provoque un plantage (il n'y a pas que les OC, si tu vas du
côté de l'embarqué ou d'archis un peu anciennes tu as des modèles de
mémoire très différents. Un avantage de C est que les définitions
s'appliquent aussi sur ces archis, permettant d'avoir une très grosse
majorité de code portable (en C strict) et quelques pourcents du code
spécifiques à l'archi.

--
Le travail n'est pas une bonne chose. Si ça l'était,
les riches l'auraient accaparé
Avatar
Jean-Marc Bourguet
Taurre writes:

Merci pour vos réponses, j'y vois désormais plus clair à ce sujet :)
Il me reste cependant une petite question :

J'ai reverifie ma norme, la comparaison entre pointeurs non correles est bien
une "undefined behavior".
Il peut donc se passer relativement n'importe quoi dans le cadre du C standard.



C'est en effet ce qui me perturbe. Que la mémoire soit ou non
segmentée, les pointeurs restent des entiers, les comparer ne doit
donc pas poser de problème. Existe-t-il des architectures où une telle
comparaison provoquerait une erreur (comme par exemple l'émission d'un
signal) ?



Pour commencer, dans une architecture segmentée, les pointeurs sont des
paires dont les premiers éléments ne sont pas nécessairement logiquement
ordonnés et qui peuvent avoir des équivalences non triviales.

D'une part, si on quelque chose unspecified behavior, il faut donner la
liste des comportements possibles, ce qu'on n'a pas nécessairement envie de
faire.

De plus reprends l'exemple que j'ai donné (p1 <= p2 && p1 >= p2 && p1 ! p2, on peut avoir aussi p1 < p2, p2 < p3 et p4 == p3, p4 < p1) et imagine
ce que ça peut donner si tu as un optimiseur qui suppose raisonnablement
que ça ne peut pas être le cas (et on n'a peut-être pas envie de compliquer
l'optimiseur pour lui apprendre quand il ne faut pas supposer ça).


La comparaison entre pointeurs arbitraires est parfois utile. C++ fournit
std::less pour comparer les pointeurs et de mémoire POSIX impose un ordre
total dans tous les cas (j'ai pas le temps de vérifier, si quelqu'un l'a,
j'apprécierais la confirmation). On aurait aussi pu désirer que le cas de
void* soit définit de la même manière, ce qui aurait fournit la possibilité
de l'avoir en C sans trop géner les implémentations, mais ce n'est pas le
cas.

A+

--
Jean-Marc
FAQ de fclc: http://www.levenez.com/lang/c/faq
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Avatar
espie
In article ,
Taurre wrote:
Merci pour vos réponses, j'y vois désormais plus clair à ce sujet :)
Il me reste cependant une petite question :

J'ai reverifie ma norme, la comparaison entre pointeurs non correles est bien
une "undefined behavior".
Il peut donc se passer relativement n'importe quoi dans le cadre du C


standard.

C'est en effet ce qui me perturbe. Que la mémoire soit ou non
segmentée, les pointeurs restent des entiers, les comparer ne doit
donc pas poser de problème. Existe-t-il des architectures où une telle
comparaison provoquerait une erreur (comme par exemple l'émission d'un
signal) ?



Il faut *vraiment* que tu changes de mode de fonctionnement vis-a-vis du
langage, ca t'evitera des problemes.

Les questions du genre "je ne comprend pas, sur toutes les archis que je
connais, ca marche comme ca, comment peut-on faire autrement", c'est la
meilleure facon de chercher les emmerdes.

Il y *a* des archis exotiques. Tous les "undefined behavior" de la norme
en proviennent. Dans certains cas, tu vas avoir du mal a avoir une "preuve
d'existence", sous forme d'une archi sur laquelle ca chie (deja, tu auras
parfois du mal a trouver des gens qui ont ces archis sous la main ou qui en
ont eu l'experience).

Si tu pars dans l'idee de "oh ben, ca doit etre implemente comme ca, parce
que je n'arrive pas a imaginer que ca puisse etre autrement", tu auras tot
ou tard des problemes. Plutot tot, en fait, Murphy aidant. Suffit que tu
depende d'un comportement mal defini pour que quelqu'un essaie de faire
tourner ton code sur une archi ou ca chie (ca ne rate presque jamais).

Et meme: c'est un mauvais etat d'esprit pour faire du code robuste, donc
de qualite, et encore plus si tu veux faire de la securite informatique.

Il faut beaucoup, beaucoup d'imagination pour trouver toutes les facons dont
un code peut merder. Mais en fait, ca n'est pas important, parce qu'il y a
une seule facon dont ce code peut marcher... c'est beaucoup plus simple,
et infiniment moins generateur d'emmerdes, de decider qu'on va se placer
dans LE cas ou les choses marchent, LE cas du comportement defini.

A force de vouloir avoir des contre-exemples... on en oublierait presque
qu'au final, le but, c'est de faire des choses qui fonctionnent.
1 2 3