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

Warning g++ non expliqué

9 réponses
Avatar
jz
Bonjour

J'ai extrait d'un programme le code minimal suivant :
-----------------------------------
#include <iostream>
class truc {
int Ni;
void print ();
int test (int i);
};
void truc::print () {
std::cout << test (Ni-2);
}
int truc::test (int i) {
return (i<Ni) ? 1 : 2;
}
-----------------------------------

Avec g++ version 4.4.1 :
g++ -c -O2 -Wall truc.cpp
truc.cpp: In member function ‘void truc::print()’:
truc.cpp:11: warning: assuming signed overflow does not occur when
assuming that (X - c) <= X is always true

Ici le test (i<Ni) est toujours vrai, ce qui semble déranger g++.

Il n'y a plus de warning sans le -O2, ou avec des unsigned int (mais
j'ai besoin de int dans le vrai prog).

Je ne me vois pas écrire une fonction test() spécialisée pour les cas où
le test est inutile, d'autant plus que ces cas ne sautent pas aux yeux
dans le vrai prog comme ici (constantes et macros réparties dans
plusieurs fichiers), ou alors autant jeter la machine et tout calculer à
la main si elle ne veut plus bosser pour nous.

Fais-je une ânerie que je ne vois pas, ou bien est-ce g++ ?

Merci,
A+
Jacques

9 réponses

Avatar
Fabien LE LEZ
On Thu, 14 Jan 2010 00:07:56 +0100, jz :

Fais-je une ânerie que je ne vois pas, ou bien est-ce g++ ?



Apparemment c'est g++ :
http://www.airs.com/blog/archives/120
Avatar
Jean-Marc Bourguet
jz writes:

Ici le test (i<Ni) est toujours vrai, ce qui semble déranger g++.



Ca ne le derange pas. J'ai pas verifie exactement ce qu'il fait -- et
encore moins cherche a le faire version par version -- mais voici ma
comprehension des choses.

Le test "i < i - 2" (qui est en cause ici apres inlining) est un
comportement indefini. Face a de tels comportements, il y a -- au moins --
deux ecoles.

Celle qui dit "le compilateur peut faire n'importe quoi et il faut en
profiter pour optimiser le cas defini". Donc supprimer le test.

La deuxieme dit "C est un langage de base niveau, il faut faire ce qui est
naturel pour la machine cible, c'est a dire que le test doit etre vrai en
cas d'overflow; d'autant plus que c'est le comportement historique des
compilateurs C. Le comportement est formellement indefini mais c'est pour
permettre une implementation naturelle du C sur des machines exotiques, pas
pour laisser faire n'importe quoi sous pretexte d'optimisations".

Par defaut, g++ se comporte suivant la premiere ecole, mais donne un
warning. Il y a un flag (-fwrapv si j'ai bonne memoire) qui le fait se
comporter suivant la deuxieme.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Avatar
Jean-Marc Bourguet
Jean-Marc Bourguet writes:

jz writes:

> Ici le test (i<Ni) est toujours vrai, ce qui semble déranger g++.

Ca ne le derange pas. J'ai pas verifie exactement ce qu'il fait -- et
encore moins cherche a le faire version par version -- mais voici ma
comprehension des choses.

Le test "i < i - 2" (qui est en cause ici apres inlining) est un
comportement indefini. Face a de tels comportements, il y a -- au moins --
deux ecoles.

Celle qui dit "le compilateur peut faire n'importe quoi et il faut en
profiter pour optimiser le cas defini". Donc supprimer le test.

La deuxieme dit "C est un langage de base niveau, il faut faire ce qui est
naturel pour la machine cible, c'est a dire que le test doit etre vrai en
cas d'overflow; d'autant plus que c'est le comportement historique des
compilateurs C. Le comportement est formellement indefini mais c'est pour
permettre une implementation naturelle du C sur des machines exotiques, pas
pour laisser faire n'importe quoi sous pretexte d'optimisations".

Par defaut, g++ se comporte suivant la premiere ecole, mais donne un
warning. Il y a un flag (-fwrapv si j'ai bonne memoire) qui le fait se
comporter suivant la deuxieme.



En passant, si tu utilises des unsigned, le test est vrai en cas
d'overflow et tout le monde est d'accord la dessus.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Avatar
jz
Fabien LE LEZ a écrit :
On Thu, 14 Jan 2010 00:07:56 +0100, jz :

Fais-je une ânerie que je ne vois pas, ou bien est-ce g++ ?



Apparemment c'est g++ :



ouf ;)
merci

a+
Jacques
Avatar
jz
Jean-Marc Bourguet a écrit :

Merci pour la réponse détaillée.

Le test "i < i - 2" (qui est en cause ici apres inlining) est un
comportement indefini. Face a de tels comportements, il y a -- au moins --
deux ecoles.



En fait ici c'est dans le sens i-2<i que le warning apparaît. Par contre
là où ça devient vraiment surprenant, c'est que en remplaçant -2 par -1
le warning disparaît.

Donc "i-2<i" risquerait d'être indéfini en cas de débordement (ça je
conçois), mais pas "i-1<i" ?

J'ai du mal à percevoir la logique.

A+
Jacques
Avatar
Jean-Marc Bourguet
jz writes:

Jean-Marc Bourguet a écrit :

Merci pour la réponse détaillée.

> Le test "i < i - 2" (qui est en cause ici apres inlining) est un
> comportement indefini. Face a de tels comportements, il y a -- au moins --
> deux ecoles.

En fait ici c'est dans le sens i-2<i que le warning apparaît. Par contre là
où ça devient vraiment surprenant, c'est que en remplaçant -2 par -1
le warning disparaît.

Donc "i-2<i" risquerait d'être indéfini en cas de débordement (ça je
conçois), mais pas "i-1<i" ?



Je ne connais pas leur raisonnement. Une possibilite est qu'ils ne donnent
pas de warnings parce que le cas avec -1 est trop commum de maniere
legitime -- et un warning donne trop souvent quand le code est legitime
perds beaucoup de son interet. Une autre est que le cas avec -1 est traite
de maniere particuliere pour d'autres raisons et que personne n'a pense a
mettre le warning dans ce chemin d'execution la.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Avatar
Jean-Marc Desperrier
Jean-Marc Bourguet wrote:
En passant, si tu utilises des unsigned, le test est vrai en cas
d'overflow et tout le monde est d'accord la dessus.



Euh, pourquoi ? Pour les unsigned, le fait de boucler sur UINT_MAX en
cas d'overflow est un comportement défini ?
Avatar
espie
In article <hj1s2u$9gl$,
Jean-Marc Desperrier wrote:
Jean-Marc Bourguet wrote:
En passant, si tu utilises des unsigned, le test est vrai en cas
d'overflow et tout le monde est d'accord la dessus.



Euh, pourquoi ? Pour les unsigned, le fait de boucler sur UINT_MAX en
cas d'overflow est un comportement défini ?



Les unsigned, c'est de l'arithmetique dans Z/nZ, avec n qui vaut la puissance
de 2 adequate. Et c'est un comportement garanti:

unsigned int i = UINT_MAX;
i+=3;
assert(i == 2);
Avatar
Jean-Marc Desperrier
Marc Espie wrote:
Les unsigned, c'est de l'arithmetique dans Z/nZ,
[...] c'est un comportement garanti:



OK, merci