【问题标题】:Linked List in C and getifaddrs()C 中的链表和 getifaddrs()
【发布时间】:2013-09-21 14:41:14
【问题描述】:

我对链表有疑问。我正在使用 getifaddrs() 在 Linux 中获取 ifaces 信息。

首先,我创建了一个结构来保存接口信息。

这是一个结构:

  typedef struct iface {
    char * interface_name;
    char * interface_addr_ipv4;
    char * interface_addr_ipv6;
    char * interface_netmask;
    char * interface_broadcast;
    char * interface_mac_addr;
    int interface_active;
    struct iface * next_interface;

    } Interface;

在此之后,我以这种方式识别系统的所有ifaces,即使它们没有配置IP:

    if (getifaddrs(&ifaddr) == -1)
        return GET_INFO_IFACES_FAILED;
    struct iface * iface_aux;
    struct ifaddrs * ifaddr_aux;
    struct sockaddr_in * ip;

    iface_aux = iface;
    for (ifaddr_aux=ifaddr;ifaddr_aux!=NULL;ifaddr_aux=ifaddr_aux->ifa_next) {
        iface_aux->interface_name = ifaddr_aux->ifa_name;

        if (ip->sin_family == AF_PACKET) {
            get_interface_mac_addr(iface_aux);
            iface_aux->interface_addr_ipv4 = NULL;
            iface_aux->interface_addr_ipv6 = NULL;
            iface_aux->next_interface = (Interface *) malloc(sizeof (Interface));
            iface_aux = iface_aux->next_interface;
            iface_aux->next_interface = NULL;
        }
    }

毕竟,我做其他循环来获取接口的IP地址,这是代码:

iface_aux = iface; //go to the firts pointer
for (ifaddr_aux=ifaddr;ifaddr_aux!=NULL;ifaddr_aux=ifaddr_aux->ifa_next) {
    ip = (struct sockaddr_in *) ifaddr_aux->ifa_addr;
    if (ip->sin_family == AF_INET) {
        get_interface_ifaddr(iface_aux, ip);
        get_interface_netmask(iface_aux, ifaddr);
        get_interface_broadcast(iface_aux, ifaddr);
        iface_aux = iface_aux->next_interface;
    }
}

get_interface_ifaddr函数代码为:

int get_interface_ifaddr(Interface * iface, struct sockaddr_in * ip) {
    iface->interface_addr_ipv4 = inet_ntoa(ip->sin_addr);
    if (iface->interface_addr_ipv4 == NULL)
       return GET_IFADDR_FAILED;
    return GET_IPADDR_SUCCESS;
}

问题是,当我做另一个循环来查看接口信息时,列表的所有节点都保留最后一个 ip:

for (iface_aux=iface;iface_aux->next_interface!=NULL;iface_aux=iface_aux->next_interface) {
    printf("Interface Name: %s\n", iface_aux->interface_name);
    printf("Interface IP: %s\n", iface_aux->interface_addr_ipv4);
}

奇怪的是接口的名称是正确的,但是当我得到地址时,列表的所有节点都指向同一个地址。

有人知道发生了什么吗?

PS:我是 c 和链表的新手。

感谢您的关注。

【问题讨论】:

    标签: c++ c linux linked-list


    【解决方案1】:

    inet_ntoa 使用相同的内存区域返回结果。需要自己分配interface_addr_ipv4,手动复制数据。

    char *tmp = inet_ntoa(ip->sin_addr);
    iface->interface_addr_ipv4 = malloc(sizeof(char) * (strlen(tmp) + 1)); /* Don't forget to free() */
    strcpy(iface->interface_addr_ipv4, tmp);
    

    来自docs

    inet_ntoa() 在静态缓冲区中返回点和数字字符串,每次调用函数都会覆盖该缓冲区。

    更好的方法就是使用inet_ntop:

    inet_ntop(AF_INET, ip->sin_addr,
              iface->interface_addr_ipv4, sizeof(iface->interface_addr_ipv4));
    

    iface->interface_addr_ipv4 是一个字符数组:

    char interface_addr_ipv4[INET_ADDRSTRLEN];
    

    【讨论】:

    • 这就是为什么 OP(和其他任何人)应该停止使用 inet_ntoa 而开始使用 inet_ntop
    • 那么,我使用 malloc 为 interface_addr_ipv4 分配内存中的其他空间?像这样。 iface->interface_addr_ipv4 = (char *) malloc(sizeof(char) + 20); iface->interface_addr_ipv4 = inet_ntoa(ip->sin_addr);
    • 是的,或者只是将其设为数组并使用inet_ntop(然后不需要strncpy)。
    • 我只是不明白我需要谁免费()。谁是?
    • 如果你用malloc分配你的内存,当你不再需要它时,你需要用free(iface->interface_addr_ipv4)释放它,以避免内存泄漏。请注意,您可以跳过malloc 并将内存分配为char interface_addr_ipv4[INET_ADDRSTRLEN];。在这种情况下,您不需要free
    猜你喜欢
    • 2016-08-18
    • 1970-01-01
    • 2014-03-29
    • 2021-02-27
    • 1970-01-01
    • 2011-10-09
    • 2018-01-01
    • 2020-08-22
    • 2015-12-01
    相关资源
    最近更新 更多