这两行在gdb
中产生以下输出。请注意,两个临时字符串first_str
和second_str
的地址具有相同的地址。那是为什么?
char *first_str = inet_ntoa(first->dest);
char *second_str = inet_ntoa(second->dest);
(gdb) p first_str
$3 = 0x7ffff7ff06d8 "54.208.71.98"
(gdb) p second_str
$4 = 0x7ffff7ff06d8 "54.208.71.98"
first->dest
和second->dest
包含不同的值。
答案 0 :(得分:8)
inet_ntoa使用静态缓冲区来实现它,所以基本上每个调用都将ascii ip地址写入同一个地方。见下文:
https://www.opensource.apple.com/source/Libc/Libc-167/net.subproj/inet_ntoa.c
char *
inet_ntoa(in)
struct in_addr in;
{
static char b[18];
register char *p;
p = (char *)∈
#define UC(b) (((int)b)&0xff)
(void)snprintf(b, sizeof(b),
"%d.%d.%d.%d", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3]));
return (b);
}
您应该使用inet_ntop。
inet_ntop还具有支持IPv6的额外好处,任何新编写的代码都应该支持IPv6。
inet_ntop的用法:
char ip[INET_ADDRSTRLEN];
if (!inet_ntop(AF_INET, &addr.sin_addr, ip, sizeof(ip))) {
/// do something with error
}
答案 1 :(得分:2)
来自inet_ntoa
docs:
“应用程序不应该对内存的分配方式做任何假设。返回的字符串保证只有在同一个线程中进行下一个Windows套接字函数调用之后才有效。”
它似乎只使用静态缓冲区。因此,您需要在下次调用之前将结果复制到新缓冲区。