inet_ntoa不可重入性
在使用inet_ntoa时, 碰到一个很奇观的现象。
代码如下:
fprintf(stdout, "recv from %s:%d %d and send to %s:%d %d\\n", inet\_ntoa(from.sin\_addr), ntohs(from.sin\_port), len, inet\_ntoa(to.sin\_addr), ntohs(to.sin\_port), s);
分析输出log, 发现除了to.sin_addr, 其他参数都是正确的;to.sin_addr的输出值为from.sin_addr值;但使用gdb来debug发现, to.sin_addr是正确的,也就是说输出到标准输出设备(stdout)上的值, 不是to.sin_addr的值。
查看inet_ntoa的在线手册:
The inet_ntoa() function converts the Internet host address in, given in network byte order, to a string in IPv4 dotted-decimal notation. The string is returned in a statically allocated buffer, which subsequent calls will overwrite.
很明显, inet_ntoa是不可重入的,每次调用都返回已分配好的一段memory地址,也就是说inet_ntoa的返回值(一个char*指针)是固定的,但memory中包含的内容不一样。 在上述代码中, 在计算fprintf参数时, inet_ntoa被调用了两次,第一次的调用结果被第二次覆盖住;输出结果也反应了参数的入栈顺序为从右到左。
结论:
- inet_ntoa 是不可重入的,在多线程的环境下要更加注意
- 每次调用inet_ntoa都会覆盖上次调用的计算结果, 要注意保存结果
另外, 为support IPV6, 推荐使用inet_ntop函数。