c - 当 ZMQ_FD option_val 的本地地址通过时,zmq_getsockopt 在 Windows x64 上返回 EINVAL

标签 c windows 64-bit zeromq mingw-w64

在 Windows x64 上,将局部变量的地址传递给 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 注释掉的形式没有问题。这对我来说毫无意义,因为将局部变量的地址传递给 zmq_getsockopt 是完全合法的。

此问题仅在 Windows 上的 64 位二进制文​​件中出现; Windows 上的 32 位二进制文​​件或 Linux 上的 64 位二进制文​​件没有问题。

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

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

更新

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

sizeof(fd)

采用第二种形式的指针 的大小。事实上,它与 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 上使用 ZMQ_FD 的 64 位整数类型

/* 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。这是一个错误吗? Windows 异常?我很笨吗?

相关附录:

zmq version: 3.2.3

compiler: cross compiled using mingw-w64, rubenvb-4.8.0 build for both 64bit and 32bit binaries

os: windows 7

最佳答案

zmq_getsockopt 手册页说,

Option value type int on POSIX systems, SOCKET on Windows

关于c - 当 ZMQ_FD option_val 的本地地址通过时,zmq_getsockopt 在 Windows x64 上返回 EINVAL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18607915/

相关文章:

c - isalpha() 和 isdigit() 总是返回 0

c# - 在 C# 中监视文件/目录访问

windows - .cmd 文件中的 pushd %~dp0 是什么意思?我理解 %~dp0 表示它表示一个驱动器号

ios - 使用 NSInteger 而不是 int 的好处?

c++ - 非常大的枚举器(> 64 位类型)

c - 我怎么能初始化一个分配了零字节的指针呢?

c - 向所有线程发送信号

c - 从C中的文本文件中提取和显示数据

windows - 为什么 windows shell 的 for 命令会替换分号?

c++ - 将矩阵的行乘以 vector (低级优化)?