Windows x64上传递一个局部变量的地址zmq_getsockopt为ZMQ_FD始终如一地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第二,注释掉形式没有问题。 这使得零意义,我因为通过局部变量的地址zmq_getsockopt是完全合法的。
此问题仅在Windows 64位二进制表现; 在Windows或32位二进制的Linux 64位二进制文件没有问题。
这似乎也只能用ZMQ_FD套接字选项的问题。 ZMQ_TYPE和ZMQ_SNDHWM工作没有问题。
是否有相关的ZMQ_FD Windows x64上,我是不知道的一些奇怪的行为?
更新
所以,我只注意到我的“工作”的代码实际上是错误的。
sizeof(fd)
是服用的sizeof一个指针在所述第二形式。 事实上,没有任何使用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"); }
事实证明,我显然需要Windows x64上使用64位整型与ZMQ_FD
/* 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,rubenvb-4.8.0编译构建这两个64位和32位二进制文件
操作系统:Windows 7