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

问题描述 投票:0回答:2

我们目前正在开发一种小工具,它可以读取CAN消息并评估所包含的数据。当char数组bind()太短,太长或不存在时,empty命令不返回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数组来成功绑定?

c linux sockets bind can-bus
2个回答
4
投票

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

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

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

它完全成功比失败取决于empty阵列的大小这一事实更令人惊讶。您希望套接字绑定到哪个地址?


3
投票

我们按照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可以完全修复这种意外行为。

感谢大家。

© www.soinside.com 2019 - 2024. All rights reserved.