"warning: dereferencing type-punned pointer will break strict-aliasing rules"

Le
JKB
Bonjour à tous,

J'ai lors de la compilation d'un programme plusieurs warnings que je
ne comprends pas.

Exemple minimal :

factorisation_lu((*s_objet_argument).objet, (struct_matrice **)
&((*s_objet_resultat_1).objet), &ios);

me renvoie lors de la compilation (avec gcc-4.2 comme compilo) :

instructions_l4.conv.c: In function librpl_instruction_lu:
instructions_l4.conv.c:149: warning: dereferencing type-punned pointer
will break strict-aliasing rules.

Le prototype de la fonction (écrite en Fortran90) est le suivant :

void factorisation_lu(struct_matrice *s_matrice,
struct_matrice **s_permutation, long *ios);

et le type struct_matrice est :

typedef struct matrice
{
unsigned long nombre_lignes;
unsigned long nombre_colonnes;
unsigned char type;
void **tableau;
} struct_matrice;

Comment faire pour supprimer ce warning ? Je ne vois pas vraiment ce
que j'ai fait de mail (si tant est que j'ai écrit quelque chose
d'incorrect).

Cordialement,

JKB

--
Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Xavier Roche
Le #1550814
(struct_matrice **) &((*s_objet_resultat_1).objet)


Pourquoi avoir besoin de caster en "struct_matrice **" ? Sur quelle
ligne exactement le warning est levé ?

(Accessoirement le membre "objet" est bien de type struct_matrice * ?)

JKB
Le #1550813
Le 12-03-2008, à propos de
Re: "warning: dereferencing type-punned pointer will break strict-aliasing rules",
Xavier Roche écrivait dans fr.comp.lang.c :
(struct_matrice **) &((*s_objet_resultat_1).objet)


Pourquoi avoir besoin de caster en "struct_matrice **" ? Sur quelle
ligne exactement le warning est levé ?


Sur cette ligne :

(struct_matrice **) &((*s_objet_resultat_1).objet), &ios);

Si je vire le cast, j'obtiens ceci :

instructions_l4.conv.c:149: warning: passing argument 2 of
librpl_factorisation_lu from incompatible pointer type

car le champ objet est un pointeur sur un void. Ce champ peut
pointer sur des entiers, des réels, des complexes, des vecteurs, des
matrices, enfin sur tout un tas d'objets mathématiques.

Définition de struct_objet :

typedef struct objet
{
unsigned char type[4];
long nombre_occurrences;
void *objet;
} struct_objet;

En particulier, objet pointe sur une matrice lorsque type vaut "MIN"
(matrice d'entiers), "MRL" (matrice de réels) ou "MCX" (matrice de
complexes).

(Accessoirement le membre "objet" est bien de type struct_matrice * ?)


Non, c'est un pointeur sur un void. Néanmoins, lorsque cette
fonction est appelée, il s'agit _toujours_ d'un pointeur sur une
struct_matrice.

Cordialement,

JKB

--
Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.


JKB
Le #1550810
Le 12-03-2008, à propos de
"warning: dereferencing type-punned pointer will break strict-aliasing rules",
JKB écrivait dans fr.comp.lang.c :
Bonjour à tous,

J'ai lors de la compilation d'un programme plusieurs warnings que je
ne comprends pas.

Exemple minimal :

factorisation_lu((*s_objet_argument).objet, (struct_matrice **)
&((*s_objet_resultat_1).objet), &ios);

me renvoie lors de la compilation (avec gcc-4.2 comme compilo) :

instructions_l4.conv.c: In function librpl_instruction_lu:
instructions_l4.conv.c:149: warning: dereferencing type-punned pointer
will break strict-aliasing rules.

Le prototype de la fonction (écrite en Fortran90) est le suivant :

void factorisation_lu(struct_matrice *s_matrice,
struct_matrice **s_permutation, long *ios);

et le type struct_matrice est :

typedef struct matrice
{
unsigned long nombre_lignes;
unsigned long nombre_colonnes;
unsigned char type;
void **tableau;
} struct_matrice;

Comment faire pour supprimer ce warning ? Je ne vois pas vraiment ce
que j'ai fait de mail (si tant est que j'ai écrit quelque chose
d'incorrect...).


Après autre investigation, le warning n'apparaît qu'à partir de
l'optimisation -O2. Je ne sais pas trop ce que fait le compilo sur
cette ligne, mais je viens de m'en tirer en écrivant :

s_matrice= (struct_matrice *) (*s_objet_resultat_1).objet;
factorisation_lu((*s_objet_argument).objet, &s_matrice, &ios);

avec la déclaration liminaire struct_matrice *s_objet;

Mais je reste ouvert à toute forme d'explication. Pour information,
le warning apparaît sur sparc64 (userland 32 bits) et amd64. Je n'ai
pas testé sur architecture 32 bits.

Cordialement,

JKB

--
Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.

Xavier Roche
Le #1550809
car le champ objet est un pointeur sur un void. Ce champ peut
pointer sur des entiers, des réels, des complexes, des vecteurs, des
matrices, enfin sur tout un tas d'objets mathématiques.


Ah, l'erreur est là: vous avez un pointeur casté dans un autre type et
immédiatement déréférencé ( *( (struct_matrice **) &foo ), ce qui pose
problème au compilateur car deux pointeurs quasi-identiques mais de
types différents vont exister au même moment ("quasi-identiques" ==
identiques au signe près, en gros).

Au lieu d'un void*, vous pouvez (devriez) utilier une union "propre" du
type:

typedef union opaque
{
struct_matrice *mat;
char *string;
float *flt;
void *data;
} opaque_data;

Dans ce cas, il suffit d'utiliser "&foo.opaque.mat" sans aucun cast.
Aucun autre cast ne devrait être nécessaire, au passage, après ça.

Sinon je conseille vivement cette excellente page d'une clarté
exceptionnelle sur l'aliasing, qui est un poil technique mais qui
explique non seulement ce qu'est l'aliasing, mais également l'interêt de
s'y conformer pour le compilateur:

JKB
Le #1550808
Le 12-03-2008, à propos de
Re: "warning: dereferencing type-punned pointer will break strict-aliasing rules",
Xavier Roche écrivait dans fr.comp.lang.c :
car le champ objet est un pointeur sur un void. Ce champ peut
pointer sur des entiers, des réels, des complexes, des vecteurs, des
matrices, enfin sur tout un tas d'objets mathématiques.


Ah, l'erreur est là: vous avez un pointeur casté dans un autre type et
immédiatement déréférencé ( *( (struct_matrice **) &foo ), ce qui pose
problème au compilateur car deux pointeurs quasi-identiques mais de
types différents vont exister au même moment ("quasi-identiques" ==
identiques au signe près, en gros).

Au lieu d'un void*, vous pouvez (devriez) utilier une union "propre" du
type:

typedef union opaque
{
struct_matrice *mat;
char *string;
float *flt;
void *data;
} opaque_data;

Dans ce cas, il suffit d'utiliser "&foo.opaque.mat" sans aucun cast.
Aucun autre cast ne devrait être nécessaire, au passage, après ça.


Oui, bon, je verrai ça quand j'aurai du temps (il me faudrait
corriger le truc dans un bout de code de deux cent mille lignes...),
et comme je n'ai que six warning de compilation qui sont tous de ce
type, je vais commencer par corriger ça en passant par un pointeur
intermédiaire.

Sinon je conseille vivement cette excellente page d'une clarté
exceptionnelle sur l'aliasing, qui est un poil technique mais qui
explique non seulement ce qu'est l'aliasing, mais également l'interêt de
s'y conformer pour le compilateur:


Merci pour les informations,

JKB

--
Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.


Xavier Roche
Le #1550807
Après autre investigation, le warning n'apparaît qu'à partir de
l'optimisation -O2.


-fstrict-aliasing est activé avec -O2, -O3, et -Os (man gcc)

je viens de m'en tirer en écrivant :
s_matrice= (struct_matrice *) (*s_objet_resultat_1).objet;
factorisation_lu((*s_objet_argument).objet, &s_matrice, &ios);


Humm, ça devrait marcher, mais c'est moins propre qu'une union.

Mais je reste ouvert à toute forme d'explication.


La page de Mike Acton est à lire, mais en gros le compilateur se permet,
lorsqu'il optimise sérieusement, de considérer qu'une adresse est unique
à un moment donné pour un type donné. Cela permet notamment d'_aliaser_
des pointeurs déréférencés en un registre, en isolant chaque adresse et
en considérant que personne ne peut avoir d'effet de bord dessus à cause
d'un cast mal placé.

Charlie Gordon
Le #1650483
"Xavier Roche" news: fr89nm$prl$
Après autre investigation, le warning n'apparaît qu'à partir de
l'optimisation -O2.


-fstrict-aliasing est activé avec -O2, -O3, et -Os (man gcc)

je viens de m'en tirer en écrivant :
s_matrice= (struct_matrice *) (*s_objet_resultat_1).objet;
factorisation_lu((*s_objet_argument).objet, &s_matrice, &ios);


Humm, ça devrait marcher, mais c'est moins propre qu'une union.


Tu peux simplifier le code ci-dessus en C, sans cast inutile et avec la
syntaxe des pointeurs :

struct_matrice *s_matrice;
...
s_matrice = s_objet_resultat_l->objet;
factorisation_lu(s_objet_argument->objet, &s_matrice, &ios);

De plus, s'il est possible que la fonction FORTRAN factorisation_lu realloue
la matrice, il faudrait recopier la nouvelle valeur du pointeur dans objet
après l'appel :

s_objet_resultat_l->objet = s_matrice;

Enfin tu passes la meme matrice en entree et sortie de la fonction
factorisation_lu : l'implementation doit permettre cela ou le resultat sera
completement indefini.

Mais je reste ouvert à toute forme d'explication.


La page de Mike Acton est à lire, mais en gros le compilateur se permet,
lorsqu'il optimise sérieusement, de considérer qu'une adresse est unique à
un moment donné pour un type donné. Cela permet notamment d'_aliaser_ des
pointeurs déréférencés en un registre, en isolant chaque adresse et en
considérant que personne ne peut avoir d'effet de bord dessus à cause d'un
cast mal placé.


En résumé : les cast explicites, c'est mal ;-)

--
Chqrlie.


JKB
Le #1674050
Le 18-03-2008, à propos de
Re: "warning: dereferencing type-punned pointer will break strict-aliasing rules",
Charlie Gordon écrivait dans fr.comp.lang.c :
"Xavier Roche" news: fr89nm$prl$
Après autre investigation, le warning n'apparaît qu'à partir de
l'optimisation -O2.


-fstrict-aliasing est activé avec -O2, -O3, et -Os (man gcc)

je viens de m'en tirer en écrivant :
s_matrice= (struct_matrice *) (*s_objet_resultat_1).objet;
factorisation_lu((*s_objet_argument).objet, &s_matrice, &ios);


Humm, ça devrait marcher, mais c'est moins propre qu'une union.


Tu peux simplifier le code ci-dessus en C, sans cast inutile et avec la
syntaxe des pointeurs :


J'ai un peu de mal avec la syntaxe des pointeurs. Pour moi, un
(*xx).yyy est plus logique et plus explicite qu'un xx->yy (surtout
que j'ai des trucs qui donneraient xx->yy.zz->tt... particulièrement
illisibles.).

struct_matrice *s_matrice;
...
s_matrice = s_objet_resultat_l->objet;
factorisation_lu(s_objet_argument->objet, &s_matrice, &ios);

De plus, s'il est possible que la fonction FORTRAN factorisation_lu realloue
la matrice, il faudrait recopier la nouvelle valeur du pointeur dans objet
après l'appel :

s_objet_resultat_l->objet = s_matrice;


La fonction n'alloue rien du tout (c'est une fonction de
transformation des matrice pour une fonction Fortran77 pur jus).

Enfin tu passes la meme matrice en entree et sortie de la fonction
factorisation_lu : l'implementation doit permettre cela ou le resultat sera
completement indefini.


Non, ce n'est pas la même matrice : Le premier argument est un
s_objet_argument->objet et le deuxième un s_objet_resultat_1->objet.

Mais je reste ouvert à toute forme d'explication.


La page de Mike Acton est à lire, mais en gros le compilateur se permet,
lorsqu'il optimise sérieusement, de considérer qu'une adresse est unique à
un moment donné pour un type donné. Cela permet notamment d'_aliaser_ des
pointeurs déréférencés en un registre, en isolant chaque adresse et en
considérant que personne ne peut avoir d'effet de bord dessus à cause d'un
cast mal placé.


En résumé : les cast explicites, c'est mal ;-)


Ouaips... Pourtant, j'aime assez jouer avec des void * ;-)

JKB

--
Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.



Publicité
Poster une réponse
Anonyme