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

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

8 réponses
Avatar
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.

8 réponses

Avatar
Xavier Roche
(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 * ?)

Avatar
JKB
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.


Avatar
JKB
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.

Avatar
Xavier Roche
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:
<http://www.cellperformance.com/mike_acton/2006/06/understanding_strict_aliasing.html>

Avatar
JKB
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:
<http://www.cellperformance.com/mike_acton/2006/06/understanding_strict_aliasing.html>


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.


Avatar
Xavier Roche
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é.

Avatar
Charlie Gordon
"Xavier Roche" a écrit dans le message de
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.


Avatar
JKB
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" a écrit dans le message de
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.