[英]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));
(..)
盡管它指出尚未執行錯誤檢查,但addr
和ifr
都沒有完全初始化(就像您在此處提到的所有人一樣)。 因此,給定的示例遇到與我們的程序相同的問題。 使用像@zwol這樣的memset
初始化它們以確保在使用它們之前將所有值都設置為0可以完全解決此意外行為。
感謝大家。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.