IP 地址 char* 变量在循环从 ifa_addr 收集地址时意外更改
IP address char* variables unexpectedly changing when looping to gather addresses from ifa_addr
我正在遍历一个接口列表,试图从每个接口获取一个 IP 地址。我观察到一个奇怪的错误,其中 char* router_ip0 变量被更新为我在循环中设置的每个其他后续变量的值。
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 指针将指针分配给另一个指针有关。
in 0
IP addr0: 10.0.0.1
in 1
IP addr0: 10.1.0.1
in 2
IP addr0: 10.2.0.1
如您所见,router_ip0 的值分别更改为 router_ip1 和 router_ip2 的值。在此示例中,循环不访问接口 3。如果我注释掉 router_ip1 和 router_ip2 的分配,我会得到预期的输出
in 0
IP addr0: 10.0.0.1
in 1
IP addr0: 10.0.0.1
in 2
IP addr0: 10.0.0.1
如果有人能解释这里可能发生的事情,那将是一个很大的帮助。谢谢!
您需要使用malloc
和strcpy
将返回的字符串保存到分配的内存中。现在,您所有的 char
指针都指向堆栈上的相同地址,即从 inet_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 的 char 数组而不是 char 指针来达到相同的效果,而不必担心 malloc
和 free
.
我正在遍历一个接口列表,试图从每个接口获取一个 IP 地址。我观察到一个奇怪的错误,其中 char* router_ip0 变量被更新为我在循环中设置的每个其他后续变量的值。
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 指针将指针分配给另一个指针有关。
in 0
IP addr0: 10.0.0.1in 1
IP addr0: 10.1.0.1in 2
IP addr0: 10.2.0.1
如您所见,router_ip0 的值分别更改为 router_ip1 和 router_ip2 的值。在此示例中,循环不访问接口 3。如果我注释掉 router_ip1 和 router_ip2 的分配,我会得到预期的输出
in 0 IP addr0: 10.0.0.1
in 1 IP addr0: 10.0.0.1
in 2 IP addr0: 10.0.0.1
如果有人能解释这里可能发生的事情,那将是一个很大的帮助。谢谢!
您需要使用malloc
和strcpy
将返回的字符串保存到分配的内存中。现在,您所有的 char
指针都指向堆栈上的相同地址,即从 inet_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 的 char 数组而不是 char 指针来达到相同的效果,而不必担心 malloc
和 free
.