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

type punning / C99 / gcc 3.3

10 réponses
Avatar
Nicolas PENINGUY
Salut,

Je pensais ne pas trop être mauvais en C, mais me voilà confronté à un
élément de la norme C99 apparemment... En compilant un programme avec
GCC 3.3.1, j'obtiens l'avertissement suivant (qui conduit à l'arrêt de
la compilation) :

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

Je pourrais bien sûr utiliser l'option de compilation
no-strict-aliasing, mais je suppose qu'il vaudrait mieux régler le
problème proprement.

J'ai trouvé quelques infos intéressantes en cherchant sur Google, par
exemple ce message qui m'a permis de comprendre (à peu près) le pb :

http://www.ethereal.com/lists/ethereal-dev/200309/msg00343.html

La solution utilisée dans beaucoup de projets libres est apparemment
d'utiliser un union, mais j'ai lu néanmoins que ce n'était pas très
propre, même si c'était autorisé...

Questions :

Quel est la traduction correcte de "type punning" ?
Est-ce que l'utilisation de cette technique révèle une erreur de
conception du programme ?



Pour info le programme en question est gnome-build, et l'erreur est la
suivante :

typedef GType (*GluePluginGetTypeFunc) (GluePlugin *plugin, const char
*name);

...

GluePluginGetTypeFunc get_type_func;

... (gpointer *)&get_type_func <-- c'est ici que ça coince


Merci,

Nicolas

10 réponses

Avatar
Emmanuel Delahaye
In 'fr.comp.lang.c', Nicolas PENINGUY wrote:

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

Je pourrais bien sûr utiliser l'option de compilation
no-strict-aliasing, mais je suppose qu'il vaudrait mieux régler le
problème proprement.


A priori, oui, mais quelques fois, on ne peut pas faire autrement...

J'ai trouvé quelques infos intéressantes en cherchant sur Google, par
exemple ce message qui m'a permis de comprendre (à peu près) le pb :

http://www.ethereal.com/lists/ethereal-dev/200309/msg00343.html


Tout est dit!

La solution utilisée dans beaucoup de projets libres est apparemment
d'utiliser un union, mais j'ai lu néanmoins que ce n'était pas très
propre, même si c'était autorisé...


C'est propre et c'est correct.

Questions :

Quel est la traduction correcte de "type punning" ?


"Transtypage à la barbare"

Est-ce que l'utilisation de cette technique révèle une erreur de
conception du programme ?


Moui, souvent...

Pour info le programme en question est gnome-build, et l'erreur est la
suivante :

typedef GType (*GluePluginGetTypeFunc) (GluePlugin *plugin, const char
*name);

...

GluePluginGetTypeFunc get_type_func;

... (gpointer *)&get_type_func <-- c'est ici que ça coince


C'est vrai que je n'aime pas trop ça... est-tu sûr que le cast est
nécessaire? Un cast a surtout l'inconvéniant de faire sauter les contrôles de
types. Il dit au compilateur : "Moi, programmeur, je sais ce que je fais, me
casse pas les pieds avec tes warnings..." Est-ce toujours le cas? Comment le
valider ?

--
-ed- [remove YOURBRA before answering me]
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
C-reference: http://www.dinkumware.com/manuals/reader.aspx?lib=cpp
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/

Avatar
Nicolas PENINGUY

C'est propre et c'est correct.


Je viens de faire la connerie de lire ce thread :

http://groups.google.fr/groups?selm=clcm-20030916-0007%40plethora.net

sur comp.lang.c.moderated et je suis traumatisé maintenant. :-)

Quel est la traduction correcte de "type punning" ?


"Transtypage à la barbare"


Ok ! :)

C'est vrai que je n'aime pas trop ça... est-tu sûr que le cast est
nécessaire?


À vrai dire le programme n'est pas de moi, juste envie d'y
contribuer/d'apprendre. Je vais essayer de regarder un peu plus en
profondeur la chose...

Merci pour la réponse, c'est plus sympa que sur clcm ici ! :)


Avatar
Gabriel Dos Reis
Nicolas PENINGUY writes:

| Salut,
|
| Je pensais ne pas trop être mauvais en C, mais me voilà confronté à un
| élément de la norme C99 apparemment... En compilant un programme avec
| GCC 3.3.1, j'obtiens l'avertissement suivant (qui conduit à l'arrêt de
| la compilation) :
|
| warning: dereferencing type-punned pointer will break strict-aliasing rules
|
| Je pourrais bien sûr utiliser l'option de compilation
| no-strict-aliasing, mais je suppose qu'il vaudrait mieux régler le
| problème proprement.

Oui, il faut mieux. C'est la correction du programme qui est en jeu.

| J'ai trouvé quelques infos intéressantes en cherchant sur Google, par
| exemple ce message qui m'a permis de comprendre (à peu près) le pb :
|
| http://www.ethereal.com/lists/ethereal-dev/200309/msg00343.html

L'explication donnée est correcte.

| La solution utilisée dans beaucoup de projets libres est apparemment
| d'utiliser un union, mais j'ai lu néanmoins que ce n'était pas très
| propre, même si c'était autorisé...

Non seulement ce n'est pas propre mais ce n'est pas correct non
plus, du point de vue de la norme. Cependant, GCC donne la garantie
que si tu utilises une union pour faire ce genre de tripafouillage,
alors il fera son possible pour ne pas optimiser sous couvert
d'aliasing strict. Je crois que beaucoup de compilateurs du monde
réel donnent cette garantie mais il faudra vérifier.

| Questions :
|
| Quel est la traduction correcte de "type punning" ?

Je ne sais pas. Mais l'explication que tu as trouvée dans le lien est
correcte.

| Est-ce que l'utilisation de cette technique révèle une erreur de
| conception du programme ?

Ah très certainement :-)

| Pour info le programme en question est gnome-build, et l'erreur est la
| suivante :
|
| typedef GType (*GluePluginGetTypeFunc) (GluePlugin *plugin, const char
| *name);
|
| ...
|
| GluePluginGetTypeFunc get_type_func;
|
| ... (gpointer *)&get_type_func <-- c'est ici que ça coince

C'est quoi gpointer? Un void*?

-- Gaby
Avatar
Gabriel Dos Reis
Emmanuel Delahaye writes:

| > La solution utilisée dans beaucoup de projets libres est apparemment
| > d'utiliser un union, mais j'ai lu néanmoins que ce n'était pas très
| > propre, même si c'était autorisé...
|
| C'est propre et c'est correct.

Faux.

-- Gaby
Avatar
Gabriel Dos Reis
Nicolas PENINGUY writes:

|
| > C'est propre et c'est correct.
|
| Je viens de faire la connerie de lire ce thread :
|
| http://groups.google.fr/groups?selm=clcm-20030916-0007%40plethora.net

C'est également correct.

| sur comp.lang.c.moderated et je suis traumatisé maintenant. :-)

Pourquoi ?

-- Gaby
Avatar
Nicolas PENINGUY

| sur comp.lang.c.moderated et je suis traumatisé maintenant. :-)

Pourquoi ?


Un ton trop sec, limite agressif souvent... C'est pas forcément facile
pour quelqu'un qui maîtrise mal un domaine d'être parfaitement
rigoureux, on peut le remettre dans le droit chemin avec le sourire.

Avatar
Nicolas PENINGUY

| typedef GType (*GluePluginGetTypeFunc) (GluePlugin *plugin, const char
| *name);
|
| ...
|
| GluePluginGetTypeFunc get_type_func;
|
| ... (gpointer *)&get_type_func <-- c'est ici que ça coince

C'est quoi gpointer? Un void*?


Oui c'est bien ça... En fait ça me semble relativement simple à corriger
pour ce cas précis. Est-ce correct ?

gpointer symbol;
GluePluginGetTypeFunc get_type_func;

...

/* Récupération de l'adresse d'une fonction dans un module */
g_module_symbol (..., &symbol);
get_type_func = (GluePluginGetTypeFunc)symbol;

Merci

Avatar
Gabriel Dos Reis
Nicolas PENINGUY writes:

|
| > | typedef GType (*GluePluginGetTypeFunc) (GluePlugin *plugin, const char
| > | *name);
| > | | ...
| > | | GluePluginGetTypeFunc get_type_func;
| > | | ... (gpointer *)&get_type_func <-- c'est ici que ça coince
| > C'est quoi gpointer? Un void*?
|
| Oui c'est bien ça... En fait ça me semble relativement simple à
| corriger pour ce cas précis. Est-ce correct ?

Non, ce n'est pas correct. Il n'y a aucune garantie qu'un pointeur
vers une donnée (void*) puisse représenter sans perte d'information un
pointeur vers une fonction. En fait, un pointeur vers une fonction est
une bête vraiment différente d'un pointeur vers une donnée.

Dans ce cas-ci, le cast probablement le plus portable est vers un void(void).

typedef void (*fun_t)(void);

GluePluginGetTypeFunc get_type_func;
// ...
(fun_t)get_type_func ...

| gpointer symbol;
| GluePluginGetTypeFunc get_type_func;
|
| ...
|
| /* Récupération de l'adresse d'une fonction dans un module */
| g_module_symbol (..., &symbol);
| get_type_func = (GluePluginGetTypeFunc)symbol;

cela ne change pas le problème fondamental.

-- Gaby
Avatar
Nicolas PENINGUY

Non, ce n'est pas correct. Il n'y a aucune garantie qu'un pointeur
vers une donnée (void*) puisse représenter sans perte d'information un
pointeur vers une fonction. En fait, un pointeur vers une fonction est
une bête vraiment différente d'un pointeur vers une donnée.


Effectivement je pensais à tord qu'un pointeur sur void pouvait servir à
représenter un pointeur sur une fonction...

C'est donc cette fonction de la glib qui serait incorrecte :

/* Gets a symbol pointer from a module. */
gboolean g_module_symbol (GModule *module,
const gchar *symbol_name,
gpointer *symbol);

Celà dit je me demande si par symbol on entend seulement un pointeur sur
une fonction... Je ne me sens pas non plus le courage d'aller me
plaindre du côté des développeurs de la glib. :-)

Merci pour ces précisions, on en apprends tous les jours :-)

Avatar
Gabriel Dos Reis
Nicolas PENINGUY writes:

|
| > Non, ce n'est pas correct. Il n'y a aucune garantie qu'un pointeur
| > vers une donnée (void*) puisse représenter sans perte d'information un
| > pointeur vers une fonction. En fait, un pointeur vers une fonction est
| > une bête vraiment différente d'un pointeur vers une donnée.
|
| Effectivement je pensais à tord qu'un pointeur sur void pouvait servir
| à représenter un pointeur sur une fonction...
|
| C'est donc cette fonction de la glib qui serait incorrecte :
|
| /* Gets a symbol pointer from a module. */
| gboolean g_module_symbol (GModule *module,
| const gchar *symbol_name,
| gpointer *symbol);
|
| Celà dit je me demande si par symbol on entend seulement un pointeur
| sur une fonction... Je ne me sens pas non plus le courage d'aller me
| plaindre du côté des développeurs de la glib. :-)

Je ne suis pas certain que le type du paramètre symbol doit être
« gpointer* ». Je crois qu'un simple « gpointer » suffit.

En effet, un pointeur vers une fonction est une donnée, donc un
pointeur vers un pointeur vers une fonction est parfaitement (et
implicitement) convertible vers un « void* ».

Par exemple, en supposant que la fonction g_module_symbol soit
déclarée comme

/* Gets a symbol pointer from a module. */
gboolean g_module_symbol (GModule *module,
const gchar *symbol_name,
gpointer symbol);

il est parfaitement légitime d'écrire

GluePluginGetTypeFunc get_type_func;
// ...
g_module_symbol (my_module, "func", &get_type_func);

C'est à l'implémenteur de g_module_symbol de se débrouiller s'il veut
supporter aussi l'interrogation pour les pointeurs vers fonctions.

-- Gaby