簡體   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