從一段代碼開始:
[cpp]
view plaincopyprint?
- int test_ntoa()
- {
- struct sockaddr_in recv = {0};
- struct sockaddr_in sa = {0};
- recv.sin_addr.s_addr = -217732928;
//192.168.5.243
- sa.sin_addr.s_addr = -939415360; //192.168.5.200
- printf("ip of recv:%s ip of sa:%s\n", inet_ntoa(recv.sin_addr), inet_ntoa(sa.sin_addr));
- printf("ip of recv:%s\n", inet_ntoa(recv.sin_addr));
- printf("ip of sa :%s\n", inet_ntoa(sa.sin_addr));
- return 0;
- }
int test_ntoa()<br />{<br />struct sockaddr_in recv = {0};<br />struct sockaddr_in sa = {0};<br />recv.sin_addr.s_addr = -217732928; //192.168.5.243<br />sa.sin_addr.s_addr = -939415360; //192.168.5.200<br />printf("ip of recv:%s ip of sa:%s\n", inet_ntoa(recv.sin_addr), inet_ntoa(sa.sin_addr));<br />printf("ip of recv:%s\n", inet_ntoa(recv.sin_addr));<br />printf("ip of sa :%s\n", inet_ntoa(sa.sin_addr));<br />return 0;<br />}
結果有點詫異:
[cpp]
view plaincopyprint?
- ip of recv:192.168.5.243 ip of sa:192.168.5.243
- ip of recv:192.168.5.243
- ip of sa :192.168.1.200
ip of recv:192.168.5.243 ip of sa:192.168.5.243<br />ip of recv:192.168.5.243<br />ip of sa :192.168.1.200
C函數出現這類問題,多半是由於其實現使用了靜態記憶體所知.
google其源碼:
[cpp]
view plaincopyprint?
- char *
- inet_ntoa (struct in_addr in)
- {
- __libc_once_define (static, once);
- char *buffer;
- unsigned char *bytes;
-
- /* If we have not yet initialized the buffer do it now. */
- __libc_once (once, init);
-
- if (static_buf != NULL)
- buffer = static_buf;
- else
- {
- /* We don't use the static buffer and so we have a key. Use it
- to get the thread-specific buffer. */
- buffer = __libc_getspecific (key);
- if (buffer == NULL)
- {
- /* No buffer allocated so far. */
- buffer = malloc (18);
- if (buffer == NULL)
- /* No more memory available. We use the static buffer. */
- buffer = local_buf;
- else
- __libc_setspecific (key, buffer);
- }
- }
-
- bytes = (unsigned char *) ∈
- __snprintf (buffer, 18, "%d.%d.%d.%d",
- bytes[0], bytes[1], bytes[2], bytes[3]);
-
- return buffer;
- }
char *<br />inet_ntoa (struct in_addr in)<br />{<br /> __libc_once_define (static, once);<br /> char *buffer;<br /> unsigned char *bytes;</p><p> /* If we have not yet initialized the buffer do it now. */<br /> __libc_once (once, init);</p><p> if (static_buf != NULL)<br /> buffer = static_buf;<br /> else<br /> {<br /> /* We don't use the static buffer and so we have a key. Use it<br /> to get the thread-specific buffer. */<br /> buffer = __libc_getspecific (key);<br /> if (buffer == NULL)<br />{<br /> /* No buffer allocated so far. */<br /> buffer = malloc (18);<br /> if (buffer == NULL)<br /> /* No more memory available. We use the static buffer. */<br /> buffer = local_buf;<br /> else<br /> __libc_setspecific (key, buffer);<br />}<br /> }</p><p> bytes = (unsigned char *) ∈<br /> __snprintf (buffer, 18, "%d.%d.%d.%d",<br /> bytes[0], bytes[1], bytes[2], bytes[3]);</p><p> return buffer;<br />}
這裡使用了靜態緩衝buffer,函數把轉換後的ip寫入緩衝buffer,然後返回buffer的首地址值.
看似無奈的選擇.glibc裡的某些底層函數都使用這類處理方式.
其實也可以選擇外部傳參的做法解決:
[cpp]
view plaincopyprint?
- <pre name="code"class="cpp">char *
- inet_ntoa (struct in_addr in,
char* buf, int buflen)
- {
- ... ...
- }
<pre name="code" class="cpp">char *<br />inet_ntoa (struct in_addr in, char* buf, int buflen)<br />{<br /> ... ...<br />}
這樣的處理方式,效率略低於第一種.或許這也是glibc選擇第一種方式的原因.