POSIX a l'intention de pointer vers des variantes de struct sockaddr
pour être castable, cependant cela dépend de l'interprétation de la norme C, ce qui peut être une violation de la règle stricte d'aliasing et par conséquent UB. (Voir this answer avec des commentaires en dessous.) Je peux, au moins, confirme qu'il peut y avoir au moins un problème avec gcc: ce code imprime Bug!
avec l'optimisation activée et Yay!
avec l'optimisation disabled:Comment utiliser légalement le type-punning avec des syndicats pour convertir entre les variantes de struct sockaddr sans violer la règle stricte d'aliasing?
#include <sys/types.h>
#include <netinet/in.h>
#include <stdio.h>
sa_family_t test(struct sockaddr *a, struct sockaddr_in *b)
{
a->sa_family = AF_UNSPEC;
b->sin_family = AF_INET;
return a->sa_family; // AF_INET please!
}
int main(void)
{
struct sockaddr addr;
sa_family_t x = test(&addr, (struct sockaddr_in*)&addr);
if(x == AF_INET)
printf("Yay!\n");
else if(x == AF_UNSPEC)
printf("Bug!\n");
return 0;
}
Observer cette comportement sur un online IDE.
Pour résoudre ce problème this answer propose l'utilisation du type calembour avec les syndicats:
/*! Multi-family socket end-point address. */
typedef union address
{
struct sockaddr sa;
struct sockaddr_in sa_in;
struct sockaddr_in6 sa_in6;
struct sockaddr_storage sa_stor;
}
address_t;
Cependant, apparemment les choses ne sont pas aussi simples qu'ils regardent ... this comment par @zwol Citation:
Que peut travail, mais prend un peu de soin. Plus que je peux entrer dans cette boîte de commentaire.
Quel genre de peu juste des soins faut-il? Quels sont les pièges de l'utilisation de type punning avec les syndicats à jeter entre les variations de struct sockaddr
?
Je préfère demander que de courir dans UB.
Il n'est pas clair quel est votre problème actuel avec le «union». Que diriez-vous d'un [mcve] et plus de détails sur vos préoccupations? Pourquoi ne demandez-vous pas à zwol ce qu'il veut dire? Nous ne sommes pas clairvoyants. – Olaf
@Olaf Pourquoi ne pas demander zwol? Parce que, comme je l'ai cité, il a déjà déclaré qu'il ne souhaitait pas en parler dans les commentaires. Qu'en est-il un exemple minimal, complet et vérifiable? Eh bien, je pose cette question précisément parce que je veux éviter de tomber dans un piège inconnu de moi qui me rendrait nécessaire d'élaborer un exemple aussi minime, complet et vérifiable. Quand il s'agit de UB en C, je pense que l'expression "mieux vaut prévenir que guérir" tient complètement. – gaazkam
Je ne suis pas sûr que vous pouvez faire quelque chose sans réorganiser tout le tas d'interfaces qui impliquent sockaddr. Quoi que vous fassiez, la fonction existante attend toujours struct sockaddr * et pas n'importe quel type d'union. –