繁体   English   中英

为什么我们需要一个未使用的char数组来进行成功绑定?

[英]Why do we need an unused char array for a successfull bind?

我们目前正在开发一个小型工具,该工具可以读取CAN消息并评估其中包含的数据。 当char数组为empty ,太长或不存在时, bind()命令不会返回0(成功绑定)。 该错误出现在下面的缩短程序中。

#include <sys/socket.h>     // socket, bind, PF_CAN, SOCK_RAW
#include <linux/if.h>       // ifreq
#include <linux/can.h>      // sockaddr_can, CAN_RAW
#include <stdio.h>          // printf

int main()
{
    struct sockaddr_can addr;
    struct ifreq ifr;
    int socketFd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
    addr.can_ifindex = ifr.ifr_ifindex;

    char empty[5];     // change length or comment out to provoke the error

    if(bind(socketFd, (struct sockaddr *) &addr, sizeof(addr)) != 0)
    {
        printf("Unable to bind the CAN-socket.\n");
    }
}

行为随着我们的char数组的长度为empty 例如, [5]有效,而[24]无效。 我们用GCC 5.4.0和7.2.0对此进行了测试,它们都表明了这种行为。 在GCC 5.3.0中, empty的存在和持续时间不影响我们的bind()

作为参考,我们使用了

gcc main.c
./a.out

为什么我们需要GCC 5.4.0和7.2.0的未使用char数组才能成功绑定?

由于使用未初始化的变量,导致各种未定义的行为。

您永远不会初始化ifr ,然后使用ifr.ifr_ifindex

您永远不会初始化addr.tp ,然后将addr作为sockaddr参数传递给bind()

它完全成功比失败取决于empty数组的大小更令人惊讶。 您希望套接字绑定到什么地址?

我们遵循在kernel.org上找到的文档。

在“ 4.如何使用SocketCAN”(大约60行)中给出了以下示例:

int s;
struct sockaddr_can addr;
struct ifreq ifr;

s = socket(PF_CAN, SOCK_RAW, CAN_RAW);

strcpy(ifr.ifr_name, "can0" );
ioctl(s, SIOCGIFINDEX, &ifr);

addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;

bind(s, (struct sockaddr *)&addr, sizeof(addr));

(..)

尽管它指出尚未执行错误检查,但addrifr都没有完全初始化(就像您在此处提到的所有人一样)。 因此,给定的示例遇到与我们的程序相同的问题。 使用像@zwol这样的memset初始化它们以确保在使用它们之前将所有值都设置为0可以完全解决此意外行为。

感谢大家。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM