*Bonjour*
Tout est dans le titre. Si vous savez comment solutionner ça, je suis preneur.
*Merci d'avance*
*Bonjour*
Tout est dans le titre. Si vous savez comment solutionner ça, je suis preneur.
*Merci d'avance*
La norme du C n'exige pas qu'un pointeur sur un objet sur void puisse être converti en pointeur sur une fonction. Assigner un void * à un pointeur de fonction est donc une opération non portable, d'où le warning. Une manière de contourner le warning (autre que le désactiver) sans toutefois résoudre le problème de portabilité : utiliser memcpy au lieu de l'affectation.hook.c:7: warning: ISO C forbids assignment between function pointer and `void *'
hook.c:8: warning: ISO C forbids assignment between function pointer and `void *'
Ici la syntaxe est tout simplement non standard, il faut initialiser l'objet pendant sa définition ou alors appeler écrire une fonction d'initialisation pour être 100% conforme et donc portable.wrapper.c:19: warning: ISO C89 forbids specifying subobject to initialize
wrapper.c:20: warning: ISO C89 forbids specifying subobject to initialize
Je ne pense pas que l'ajout d'un cast puisse supprimer ce warning car le résultat sera le même : tu convertis toujours, par cast, un void * en pointeur de fonction, ce qui n'est pas portable. Mais c'est vrai qu'il faut tenter car je viens de me rendre compte que même le memcpy ne résout pas l'affaire. Si le cast non plus ne marche pas, et ben comme le code n'est pas portable, le seul moyen de supprimer le warning c'est de faire taire le compilateur (enlever aussi -pedantic et/ou -Wall et/ou -W).
Effectivement, si j'essaie sous GCC de transtyper « void * » vers le pointeur de fonction adéquat, j'obtiens une erreur parce que le compilateur considère que le pointeur, tout void soit-il, reste un pointeur d'objet et donc ne peut être transformé en pointeur de fonction :
Code C : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 int main (void) { hook_t h; h._open = (int(*)(const char *,int,mode_t))dlsym( RTLD_NEXT, "open"); h._close = (int(*)(int))dlsym( RTLD_NEXT, "close" ); return 0; }
Code Shell : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 $ gcc -pedantic -ansi -W -Wall funcptrcast.c -o funcptrcast funcptrcast.c: In function ‘main’: funcptrcast.c:5: attention : ISO C interdit la conversion d'un pointeur d'objet vers un type de pointeur à une fonction funcptrcast.c:6: attention : ISO C interdit la conversion d'un pointeur d'objet vers un type de pointeur à une fonction
C'est d'ailleurs très discutable parce que ça aurait du sens sur les architectures purement Harvard, mais ça devrait être une exception gérée par le compilo concerné et pas une généralité de la norme C puisqu'il est établi qu'un pointeur, en général, peut très bien accéder une zone de mémoire contenant du code sur la plupart des architectures conventionnelles.
Par contre, le contraire fonctionne bien !
Code C : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 *(void **)&(h._open) = dlsym( RTLD_NEXT, "open"); *(void **)&(h._close) = dlsym( RTLD_NEXT, "close" );
C'est même sensiblement plus lisible parce que plus court, moins complexe et parce que le type est le même à chaque appel.
ÉDIT : La norme C99 (enfin, n1256) spécifie explicitement cette possibilité :
Mais GCC cesse de se plaindre également dès lors que l'on enlève « -pedantic », même avec « -std=c89 ». La man page de GCC spécifie :J.5.7 Function pointer casts
1 A pointer to an object or to void may be cast to a pointer to a function, allowing data to
be invoked as a function (6.5.4).
2 A pointer to a function may be cast to a pointer to an object or to void, allowing a
function to be inspected or modified (for example, by a debugger) (6.5.4).
Je ne sais pas dans quelle section de la norme ces contrôles stricts sont définis.Issue all the warnings demanded by strict ISO C and ISO C++; reject all programs that use forbidden extensions, and some other programs that do not follow ISO C and ISO C++. For ISO C, follows the version of the ISO C standard specified by any -std option used.
[…]
Some users try to use -pedantic to check programs for strict ISO C conformance. They soon find that it does not do quite what they want: it finds some non-ISO practices, but not all---only those for which ISO C requires a diagnostic, and some others for which diagnostics have been added.
Ca marche !
Enfin disparus ces warnings et le code fonctionne toujours !
Merci à tous pour votre aide.
Obsidian est un authentique guru, merci à lui de prendre le temps de faire part de son savoir à des développeurs de mon niveau.
A l'occasion, il faudra que tu m'orientes sur un échange en MP ou un tuto balaise pour que je comprenne ces cast de fonctions qui me semblent encore bien mystérieux.
Partager