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