搞怪的调试,IP地址输出总是错误的问题。检查日志发现了一个日志中间的IP地址总是输出错误。
Dec 28 11:08:30.759 2007@LM_INFO@Listen peer [124.115.1.80|80] accept Socket IP Address:[124.115.1.80|64119] Success.
Dec 28 11:08:31.463 2007@LM_INFO@Listen peer [124.115.1.80|80] accept Socket IP Address:[124.115.1.80|1416] Success.
Dec 28 11:08:37.942 2007@LM_INFO@Listen peer [124.115.1.80|80] accept Socket IP Address:[124.115.1.80|31580] Success.
每次后面的地址总是输出错误,没有将远端地址正确显示出来,每次远端地址显示的都是本地地址。
检查日志输出的地方,代码很简单。
ACE_DEBUG((LM_INFO,"Listen peer [%s|%u] accept Socket IP Address:[%s|%u] Success. /n",
local_address_.get_host_addr(),
local_address_.get_port_number(),
remote_address_.get_host_addr(),
remote_address_.get_port_number()));
先怀疑栈被破坏,检视了代码半天,觉得没有问题,在Windows下调试,
发现问题依旧,跟踪进函数堆栈,发现ACE_DEBUG 调用函数内部2个参数的地址居然一样,抓狂。
甚至怀疑ACE的代码有问题,研究了半天ACE的变参函数的写法。(也好,终于明白了变参函数怎么写)
一次无意的跟踪到了ACE_INET_Addr get_host_addr()内部,发现了其使用的是C函数inet_ntoa,恍然大悟。
丑陋的C语言,当年为了图省事,相当的函数使用了static 成员作为函数的返回值。
这个方法在大大的方便了使用者的同时,也给使用者带来了重大的危险,使用不慎就会导致莫名的bug。
对于上面的例子来说,由于是变参函数,参数的传递顺序是从右到左。所以local_address_.get_host_addr()后入栈,所以每次返回的地址都是他的数值。
教训:
1. 永远不要做这种将指针作为函数返回值的事情。这种方式在任何重入的地方都是不安全的
2.对于别人的返回的指针也慎重使用。