zmq_getsockopt renvoie EINVAL sur Windows x64 lorsque l’adresse locale de ZMQ_FD option_val est transmise

Sous Windows x64, l’adresse d’une variable locale est transmise à zmq_getsockopt pour ZMQ_FD de manière cohérente avec EINVAL. Le code ci-dessous est le plus petit possible pour reproduire le problème.

#include  #include  void zmq_perror(const char*); int main(void) { const char *endpoint = "tcp://127.0.0.1:7100"; void *ctx = zmq_ctx_new(); if (ctx == NULL) { zmq_perror("zmq_ctx_new"); } void *socket = zmq_socket(ctx, ZMQ_DEALER); if (socket == NULL) { zmq_perror("zmq_socket"); } int rc; rc = zmq_connect(socket, endpoint); if ( rc == -1 ) { zmq_perror("zmq_connect"); } /*** This results in EINVAL ***/ int fd; size_t fd_size = sizeof (fd); rc = zmq_getsockopt(socket, ZMQ_FD, &fd, &fd_size); if (rc == -1) { zmq_perror("zmq_getsockopt"); } /*** This works without issue ***/ /* int *fd = malloc(sizeof(int)); size_t fd_size = sizeof (fd); rc = zmq_getsockopt(socket, ZMQ_FD, fd, &fd_size); if (rc == -1) { zmq_perror("zmq_getsockopt"); } */ } void zmq_perror(const char *f) { fprintf(stderr, "%s: %s\n", f, zmq_strerror(zmq_errno())); abort(); } 

L’exécution de ce qui précède à l’aide du premier formulaire (page de manuel) produit toujours:

 zmq_getsockopt: Invalid argument 

Cependant, le second formulaire commenté utilisant malloc n’a pas de problème. Cela n’a aucun sens pour moi, car transmettre l’adresse de la variable locale à zmq_getsockopt est parfaitement légal.

Ce problème ne se manifeste qu’avec des fichiers binarys 64 bits sous Windows; Les fichiers binarys 32 bits sous Windows ou 64 bits sous Linux n’ont pas de problème.

Cela semble également être un problème avec l’option de socket ZMQ_FD. ZMQ_TYPE et ZMQ_SNDHWM ont fonctionné sans problème.

Existe-t-il un comportement étrange lié à ZMQ_FD sous Windows x64 dont je ne suis pas au courant?

Mettre à jour

Donc, je viens de remarquer que mon code “de travail” est en réalité erroné.

 sizeof(fd) 

prend la taille d’un pointeur dans la deuxième forme. En fait, cela n’a rien à voir avec malloc, car une fois que je le change en sizeof (int) comme il se doit, je reçois encore EINVAL:

 /* Fail */ int *fd = malloc(sizeof(int)); size_t fd_size = sizeof(int); rc = zmq_getsockopt(socket, ZMQ_FD, fd, &fd_size); if (rc == -1) { zmq_perror("zmq_getsockopt"); } 

Il s’avère que j’ai apparemment besoin d’utiliser un type entier de 64 bits avec ZMQ_FD sur Windows x64

 /* Success! */ uint64_t fd; size_t fd_size = sizeof(uint64_t); rc = zmq_getsockopt(socket, ZMQ_FD, &fd, &fd_size); if (rc == -1) { zmq_perror("zmq_getsockopt"); } 

Ceci est très déroutant puisque l’API pour zmq_getsockopt est int . Est-ce un bug? Une excensortingcité des fenêtres? Moi être dense?

Addenda pertinent:

version de zmq: 3.2.3

compilateur: cross compilé en utilisant mingw-w64, build rubenvb-4.8.0 pour les fichiers binarys 64 bits et 32 ​​bits

os: windows 7

La page de manuel zmq_getsockopt indique:

Type de valeur d’option int sur les systèmes POSIX, SOCKET sur Windows