inet_ntoa 陷阱

前天同事问我一个关于ip被"替换"的问题,代码大概如下:

ip_ local = networkMgr.GetLocalIP();  //127.0.0.1
ip_ server = networkMgr.GetServerIP(); //0.0.0.0
printf("  l:%s",inet_ntoa(local));
printf("  s:%s \n",inet_ntoa(server));

//network manager to do something

printf("  l:%s s:%s \n",inet_ntoa(networkMgr.GetLocalIP()),inet_ntoa(networkMgr.GetServerIP())); /// 输出结果: // l:127.0.0.1 s:0.0.0.0 // l:0.0.0.0 s:0.0.0.0

"正常情况"下,下边一句应该返回 127.0.0.1 才对.可是为何会发生这种情况? 最初没留意到inet_nota 函数的作用,认为是networkMgr 在处理其他事中改变了本地IP地址导致 networkMgr.GetLocalIP() 获取到新值.熟加数据断点调试(其实不用这么麻烦,直接printf("%u",networkMgr.GetLocalIP()) 便成),发现数据没有被修改。

想起x进制转换成字符串的函数,其形式是:

char* itoa (int value, char * str, int base);

inet_ntoa 函数:

char* inet_ntoa (struct in_addr);

与inet_ntoa对比,itoa函数的字符串缓冲由参数提供,而inet_ntoa 只需提供 in_addr结构体便可(也可看成是32位无符号整形),说明inet_ntoa返回的字符串缓冲由内部提供。

返回的字符串缓冲要么由堆内存申请,需要自己手动释放;要么是返回内部静态缓冲的地址。

如果是前一种,调用者容易忘记释放内存而做成内存溢出;还有一个问题就是调用者不知道该如何释放,是调用free,还是delete[],还是_aligned_free?这种设计还需提供一个释放内存的接口,明显选择第二种方便快捷简单明了(但需要调用者注意)。

具体查看API文档:http://msdn.microsoft.com/en-us/library/windows/desktop/ms738564(v=vs.85).aspx

其实文档中已经说明内部就是返回内部静态缓冲的地址了。当然也可以直接输出来验证:

char* ls = inet_ntoa(networkMgr.GetLocalIP());
char* ss = inet_ntoa(networkMgr.GetServerIP());
printf(" l:%p s:%p \n",ls, ss);

至于为何printf 会输出 “ l:0.0.0.0 s:0.0.0.0” 而不是“ l:127.0.0.1 s:127.0.0.1”,这里可以自行查看函数调用约定以及其入栈顺序。例如 stdcall、cdecl等等。

补充:调用inet_ntoa 时还需注意多线程安全问题,建议使用 inet_ntop函数代替。

搜索了下inet_ntoa发现很多人都遇到过类似问题,甚至百度都有大量说明 = =:

C/C++返回内部静态成员的陷阱http://blog.csdn.net/haoel/article/details/1388498

inet_ntoa使用陷阱: http://hi.baidu.com/lovzs/item/cc9529089bb55e37a3332aa5

inet_ntoa百度百科:http://baike.baidu.com/view/569200.htm
原文链接: https://www.cnblogs.com/godzza/archive/2013/03/14/2957015.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/80658

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月9日 下午7:39
下一篇 2023年2月9日 下午7:40

相关推荐