【发布时间】:2018-01-31 17:36:57
【问题描述】:
我们目前正在开发一种小型工具,用于读取 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 数组才能成功绑定?
【问题讨论】:
-
addr.can_ifindex = ifr.ifr_ifindex;是未定义的行为。你从未初始化过ifr_ifindex。 -
这种事情可能是未定义行为的症状,虽然我不知道是什么。
-
应该确保所有
addr都被正确填充。 -
您应该以
memset(&addr, 0, sizeof addr); memset(&ifr, 0, sizeof ifr);开头,然后将ifr_ifr_ifindex设置为一个有意义的值,然后再将其复制到addr.can_ifindex。 (这个精简程序似乎根本不需要ifr,但我想它在实际程序中提供了一些功能。) -
使用 memset 初始化
addr和ifr解决了我们的问题。我们将ifr.ifr_name设置为我们的设备名称,将addr.can_family设置为AF_CAN,但这已被删除,因为它不会影响行为。我们的ioctl也需要ifr,它也被剪掉了。
标签: c linux sockets bind can-bus