当 ZMQ_FD option_val 的本地地址通过时,zmq_getsockopt 在 windows x64 上返回 EINVAL [英] zmq_getsockopt returns EINVAL on windows x64 when local address of ZMQ_FD option_val passed

查看:43
本文介绍了当 ZMQ_FD option_val 的本地地址通过时,zmq_getsockopt 在 windows x64 上返回 EINVAL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 windows x64 上,将局部变量的地址传递给 zmq_getsockopt 以获取 ZMQ_FD 始终会导致 EINVAL.下面的代码是重现问题的最小代码.

On windows x64 passing the address of a local variable to zmq_getsockopt for ZMQ_FD consistently results in EINVAL. The code below is the smallest possible to reproduce the problem.

#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
", f, zmq_strerror(zmq_errno()));                                                                                                                                                     
    abort();                                                                                                                                                                                                       
}

使用第一个(手册页)表单运行上述内容总是会产生:

Running the above using the first (manpage) form always produces:

zmq_getsockopt: Invalid argument

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

However the second, commented out form using malloc has no issues. This makes zero sense to me since passing the address of the local variable to zmq_getsockopt is perfectly legal.

此问题仅在 windows 上的 64 位二进制文​​件中表现出来;Windows 上的 32 位二进制文​​件或 linux 上的 64 位二进制文​​件没有问题.

This problem only manifests with 64 bit binaries on windows; 32 bit binaries on windows or 64 bit binaries on linux have no issue.

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

It also seems to only be an issue with the ZMQ_FD socket option. ZMQ_TYPE and ZMQ_SNDHWM worked without issue.

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

Is there some weird behavior related to ZMQ_FD on windows x64 that I'm not aware of?

更新

所以我只是注意到我的工作"代码实际上是错误的.

So I just noticed that my "working" code is actually erroneous.

sizeof(fd)

采用第二种形式的指针的大小.实际上,它与 malloc 无关,因为一旦我将其更改为 sizeof(int) 就应该再次获得 EINVAL:

is taking the sizeof a pointer in the second form. In fact, it has nothing to do with malloc, as once I change it to sizeof(int) as it should be I get EINVAL again:

/* 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 位整数类型

It turns out I apparently need to use a 64bit integer type with ZMQ_FD on 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"); }

这非常令人困惑,因为 zmq_getsockopt 的 api 是 int.这是一个错误吗?窗户怪癖?我很密集?

This is very confusing since the api for zmq_getsockopt is int. Is this a bug? A windows eccentricity? Me being dense?

相关附录:

zmq 版本:3.2.3

zmq version: 3.2.3

编译器:使用 mingw-w64、rubenvb-4.8.0 为 64 位和 32 位二进制文​​件交叉编译

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

操作系统:Windows 7

os: windows 7

推荐答案

zmq_getsockopt 手册页说,

The zmq_getsockopt man page says,

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

Option value type int on POSIX systems, SOCKET on Windows

这篇关于当 ZMQ_FD option_val 的本地地址通过时,zmq_getsockopt 在 windows x64 上返回 EINVAL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆