C 从ifa_addr循环收集地址时,IP地址字符*变量意外更改
我在一个接口列表中循环,试图从每个接口获取一个IP地址。我观察到一个奇怪的bug,其中char*routerip0变量被更新为我在循环中设置的每个后续变量的值C 从ifa_addr循环收集地址时,IP地址字符*变量意外更改,c,sockets,pointers,networking,ip-address,C,Sockets,Pointers,Networking,Ip Address,我在一个接口列表中循环,试图从每个接口获取一个IP地址。我观察到一个奇怪的bug,其中char*routerip0变量被更新为我在循环中设置的每个后续变量的值 char *router_ip; char *router_ip0; char *router_ip1; char *router_ip2; char *router_ip3; sockaddr_in *sa; //Loop through list of interface's for(tmp = ifaddr; tmp!=NULL;
char *router_ip;
char *router_ip0;
char *router_ip1;
char *router_ip2;
char *router_ip3;
sockaddr_in *sa;
//Loop through list of interface's
for(tmp = ifaddr; tmp!=NULL; tmp=tmp->ifa_next){
//Harvest IP address's
if(tmp->ifa_addr->sa_family==AF_INET){
if(!strncmp(&(tmp->ifa_name[3]),"eth0",4)){
printf("\nin 0\n");
sa = (struct sockaddr_in *) tmp->ifa_addr;
router_ip0 = inet_ntoa(sa->sin_addr);
printf("IP addr0: %s\n", router_ip0);
}
else if(!strncmp(&(tmp->ifa_name[3]),"eth1",4)){
printf("\nin 1\n");
sa = (struct sockaddr_in *) tmp->ifa_addr;
router_ip1 = inet_ntoa(sa->sin_addr);
printf("IP addr0: %s\n", router_ip0);
}
else if(!strncmp(&(tmp->ifa_name[3]),"eth2",4)){
printf("\nin 2\n");
sa = (struct sockaddr_in *) tmp->ifa_addr;
router_ip2 = inet_ntoa(sa->sin_addr);
printf("IP addr0: %s\n", router_ip0);
}
else{
printf("\nin 3\n");
sa = (struct sockaddr_in *) tmp->ifa_addr;
router_ip3 = inet_ntoa(sa->sin_addr);
//printf("IP addr: %s\n", router_ip1);
}
}
输出如下。我相当确信可以验证每个变量在循环中只设置一次。我怀疑这可能与将一个指针分配给另一个带有char*和sa->sin_addr指针的指针有关
在0中IP地址0:10.0.0.1 在1中
IP地址0:10.1.0.1 在2
IP地址0:10.2.0.1 如您所见,路由器_ip0的值分别更改为路由器_ip1和路由器_ip2的值。在本例中,循环不访问接口3。如果我注释掉路由器_ip1和路由器_ip2的分配,我会得到预期的输出 在0 IP地址0:10.0.0.1 在1 IP地址0:10.0.0.1 在2 IP地址0:10.0.0.1
如果有人能解释一下这里可能发生的事情,那将是一个很大的帮助。谢谢大家! 您需要使用
malloc
和strcpy
将返回的字符串保存到分配的内存中。现在,所有char
指针都指向堆栈上相同的地址,位于inet\u ntoa
返回的字符串处,当退出作用域时,该字符串将被清除,然后在下一个循环中重新创建。这将覆盖包含上一个返回字符串的堆栈内存,使其看起来像变量已更改
例如,在执行For
循环之前,可以执行以下操作:
char *result;
router_ip0 = (char*)malloc(16);
router_ip1 = (char*)malloc(16);
router_ip2 = (char*)malloc(16);
router_ip3 = (char*)malloc(16);
(16=IPv4字符串的最大长度+空终止字符的1)
然后在循环的if
块中:
...
if(!strncmp(&(tmp->ifa_name[3]),"eth0",4)){
printf("\nin 0\n");
sa = (struct sockaddr_in *) tmp->ifa_addr;
result = inet_ntoa(sa->sin_addr);
strcpy(router_ip0, result);
printf("IP addr0: %s\n", router_ip0);
}
else if...
然后在循环之后:
free(router_ip0);
free(router_ip1);
free(router_ip2);
free(router_ip3);
您还可以使用大小为16的字符数组而不是字符指针来实现相同的效果,而不必担心malloc
和free