C語言中inet_ntoa()的記憶體管理

來源:互聯網
上載者:User

今天在調試一段程式,輸出結果總是錯誤,不知道什麼原因,代碼如下:

#include <sstream><br />#include <iostream><br />#include <netinet/in.h><br />#include <arpa/inet.h><br />using namespace std;<br />void print_address(struct in_addr addr1, struct in_addr addr2)<br />{<br />ostringstream oss;<br />oss << inet_ntoa(addr1) << "|" << inet_ntoa(addr2);<br />cout << oss.str() << endl;<br />}<br />int main()<br />{<br />struct in_addr addr1, addr2;<br />inet_aton("10.0.0.1", &addr1);<br />inet_aton("10.0.0.2", &addr2);<br />print_address(addr1, addr2);<br />return 0;<br />}

本來以為程式會輸出:

10.0.0.1|10.0.0.2

可是卻大出所料,輸出的結果為:

10.0.0.1|10.0.0.1

非常奇怪,故把代碼修改為以下,以作測試:

void print_address(struct in_addr addr1, struct in_addr addr2)<br />{<br />ostringstream oss;<br />oss << inet_ntoa(addr1) << "|" << inet_ntoa(addr2);<br />cout << oss.str() << endl;<br />cout << inet_ntoa(addr1) << endl;<br />cout << inet_ntoa(addr2) << endl;<br />}

輸出還是非常奇特:

10.0.0.1|10.0.0.1<br />10.0.0.1<br />10.0.0.2

非常不解,難道是oss的問題還是其他?於是把代碼修改如下:

void print_address(struct in_addr addr1, struct in_addr addr2)<br />{<br />ostringstream oss;<br />oss << inet_ntoa(addr1) << "|" ;<br />oss << inet_ntoa(addr2);<br />cout << oss.str() << endl;<br />cout << inet_ntoa(addr1) << endl;<br />cout << inet_ntoa(addr2) << endl;<br />}

此時,程式奇怪的輸出了我想要的結果:

10.0.0.1|10.0.0.2<br />10.0.0.1<br />10.0.0.2

通過以上輸出結果,我大致猜到了原因,此時在源碼中添加以下代碼:

void print_address(struct in_addr addr1, struct in_addr addr2)<br />{<br />ostringstream oss;<br />oss << inet_ntoa(addr1) << "|" ;<br />oss << inet_ntoa(addr2);<br />cout << oss.str() << endl;<br />printf("%p %p/n", inet_ntoa(addr1), inet_ntoa(addr2));<br />printf("%p/n", inet_ntoa(addr1));<br />}

正如我所料,程式輸出:

10.0.0.1|10.0.0.2<br />0x7fed7533b6b8 0x7fed7533b6b8<br />0x7fed7533b6b8

此時可以確定了我的猜測:

oss << inet_ntoa(addr1) << "|" << inet_ntoa(addr2);在啟動並執行時候,首先執行inet_ntoa(addr2),得到一個函數指標,假設是p1;然後執行inet_ntoa(addr1),得到另一個指標,假設是p2,然後整個語句執行oss << p1 << "|" << p2;得到最後結果。問題就在這裡,其實p1, p2的值是相等的,也就是說,他們指向同一塊記憶體位址,而該段地址空間記憶體放的資料為最後一次執行inet_ntoa()時的結果。在加上oss語句是從右向左開始執行的,於是,在執行oss << p1 << "|" << p2;的時候,其實是執行了:oss << p1 << "|" << p1;於是oss中便存放了兩個相同的IP地址。

細想一下,系統開發人員這樣設計也有他自己的道理。由於inet_ntoa()函數調用是不需要使用者手動分配記憶體空間的,這樣系統就必須為這個操作分配足夠的空間。如果每一次執行該函數都分配一次空間,而使用者又沒有釋放,或者系統釋放了一次,然後使用者又釋放一次,這樣都會產生記憶體流失。所以,乾脆開發人員便開闢一段記憶體空間,每次調用都使用相同記憶體,在進程結束的時候由系統收回記憶體,如此既不浪費,也不需要使用者作繁瑣的操作。

但是還有一個問題,如果使用者手動對該記憶體段進行釋放,也會出現問題,所以建議大家不要使用類似函數,而使用使用者可以自訂記憶體位址的函數,而在這裡,inet_ntoa()函數對應的函數則為inet_ntop()。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.