当ZMQ_FD option_val的本地地址传递时,zmq_getsockopt在windows x64上返回EINVAL

在windows x64上,将局部variables的地址传递给ZMQ_FD的zmq_getsockopt将始终导致EINVAL。 下面的代码是尽可能最小的重现问题。

#include <zmq.h> #include <stdio.h> 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(); } 

使用第一个(联机帮助页)表单运行上述操作总是会产生:

 zmq_getsockopt: Invalid argument 

然而第二个使用malloc的注释表单没有问题。 这对我来说是毫无意义的,因为将局部variables的地址传递给zmq_getsockopt是完全合法的。

这个问题只能在Windows上显示64位的二进制文件; 在Windows上的32位二进制文​​件或在Linux上的64位二进制文​​件没有问题。

这似乎也只是ZMQ_FD套接字选项的问题。 ZMQ_TYPE和ZMQ_SNDHWM没有问题。

有没有一些奇怪的行为与我不知道的Windows x64上的ZMQ_FD相关?

更新

所以我只注意到我的“工作”代码实际上是错误的。

 sizeof(fd) 

以第二种forms取指针的大小。 实际上,它与malloc无关,因为一旦我将它更改为sizeof(int),就像它应该是我再次获得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"); } 

事实certificate,我显然需要在Windows x64上使用ZMQ_FD的64位整数types

 /* 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"); } 

这是非常令人困惑的,因为zmq_getsockopt的API是int 。 这是一个错误? 窗户偏心? 我正在密集?

相关附录:

zmq版本:3.2.3

编译器:使用mingw-w64进行交叉编译,为64位和32位二进制文​​件构buildrubenvb-4.8.0

操作系统:Windows 7

zmq_getsockopt手册页说,

在POSIX系统上的选项值类型为int,在Windows上为SOCKET