简体   繁体   English

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

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

We're currently developing a small tool that reads CAN-messages and evaluates the data contained. 我们目前正在开发一个小型工具,该工具可以读取CAN消息并评估其中包含的数据。 The bind() command doesn't return 0 (for a successfull bind) when the char array empty is too short, too long or not present. 当char数组为empty ,太长或不存在时, bind()命令不会返回0(成功绑定)。 This bug is present in the shortened program below. 该错误出现在下面的缩短程序中。

#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");
    }
}

The behaviour changes with the length of our char array empty . 行为随着我们的char数组的长度为empty For example [5] works, while [24] doesn't. 例如, [5]有效,而[24]无效。 We tested this with GCC 5.4.0 and 7.2.0 which both showed this behaviour. 我们用GCC 5.4.0和7.2.0对此进行了测试,它们都表明了这种行为。 Under GCC 5.3.0 the presence and lentgh of empty do not influence our bind() . 在GCC 5.3.0中, empty的存在和持续时间不影响我们的bind()

For reference we used 作为参考,我们使用了

gcc main.c
./a.out

Why do we need an unused char array with GCC 5.4.0 and 7.2.0 for a successfull bind? 为什么我们需要GCC 5.4.0和7.2.0的未使用char数组才能成功绑定?

You're causing all sorts of undefined behavior due to use of uninitialized variables. 由于使用未初始化的变量,导致各种未定义的行为。

You never initialize ifr , then you use ifr.ifr_ifindex . 您永远不会初始化ifr ,然后使用ifr.ifr_ifindex

You never initialize addr.tp , then you pass addr as the sockaddr parameter to bind() . 您永远不会初始化addr.tp ,然后将addr作为sockaddr参数传递给bind()

That it ever succeeds at all is more surprising than the fact that the failure depends on the size of the empty array. 它完全成功比失败取决于empty数组的大小更令人惊讶。 What address are you expecting the socket to be bound to? 您希望套接字绑定到什么地址?

We followed the documentation found at kernel.org . 我们遵循在kernel.org上找到的文档。

In "4. How to use SocketCAN" (approx. line 60) this example is given: 在“ 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));

(..)

While it states that no error checking has been implemented neither addr nor ifr have been fully initialised (like all of you mentioned here). 尽管它指出尚未执行错误检查,但addrifr都没有完全初始化(就像您在此处提到的所有人一样)。 Therefore the given example encounters the same problem as our program. 因此,给定的示例遇到与我们的程序相同的问题。 Initialising them with memset like @zwol mentioned to ensure all values are set to 0 before working with them fixes this unexpected behaviour completely. 使用像@zwol这样的memset初始化它们以确保在使用它们之前将所有值都设置为0可以完全解决此意外行为。

Thanks everyone. 感谢大家。

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

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