2013-06-28 34 views
4

asprintfasprintf - 何時使用free()?

功能asprintf()和vasprintf()被sprintf的類似物(3)和 vsprintf中(3),不同之處在於它們分配一個字符串大到足以容納 包括終止空輸出字節,並通過第一個參數向它返回一個指針 。 應將此指針傳遞給免費(3) 以在不再需要時釋放分配的存儲。

這裏是我的C代碼

void function(){ 
    char *out = NULL; 
    int parts[16] = {1,2,05,003}; 
    asprintf(&out, "%d.%d.%d.%d", parts[0], parts[1], parts[2], parts[3]); 
    // free(out); 
} 

int main(void){ 
    function(); 
    return 0; 
} 

當功能調試模式監控,我看到,當它從函數返回變量已經被銷燬。爲什麼我不需要free()上面的代碼?

你能告訴我,我需要使用免費什麼情況下asprintf

順便說一句,我有 「gcc版本4.7.2(Ubuntu的/ Linaro的4.7.2-2ubuntu1)」

enter image description here enter image description here

+2

不,你在那裏做的是創建一個漂亮的內存泄漏。 –

+1

你不理解動態內存的概念。多讀一點,重新思考你所做的一切。 – Dariusz

回答

10

你需要調用free()

該變量將離開作用域,因此該變量(free()需要的地址)的實際在此時會丟失,從而導致內存泄漏。

free()函數對以前由malloc()或其他堆分配調用返回的內存地址感興趣,根本不在您的特定變量中。

你可以這樣做:

char *out = NULL, *a, *b, *c, *d, *e; 
int parts[16] = {1,2,05,003}; 
asprintf(&out, "%d.%d.%d.%d", parts[0], parts[1], parts[2], parts[3]); 
a = b = c = d = e = out; 

,這只是五個變量保持相同的地址走出去的範圍的副本。當然,堆子系統(通過malloc()/free()調用達到)對此一無所知。

5

你能告訴我什麼情況下我需要使用免費的asprintf嗎?

每次,除了當asprintf返回-1。

如果存儲器分配是不可能的,或發生其他一些錯誤,這些函數將返回-1,和strp內容是未定義

例如,您可以分析valgrind輸出。

  • 沒有free呼叫:

== 3711 == HEAP內容:
== 3711 ==在使用中在出口處:在1塊
== 3711 == 8個字節總堆使用率:2個分配,1個釋放,108個字節分配

很明顯,存在內存泄漏。

  • 隨着free呼叫:

== 3722 == HEAP內容:
== 3722 ==在使用中在出口處:在0塊
== 3722 == 0字節總堆使用情況:2個分配,2個釋放,分配108個字節

4

out被「破壞」,但沒有指向什麼。後者仍然被分配,但任何提及它都會丟失。你可以考慮這是一個內存泄漏。

爲避免在離開function()之前撥打free(out)

另一種解決方案是從function返回值out,因此調用者仍然可以使用引用的內存。在另一方面呼叫者也然後採取負責釋放此內存:

char * function(void) { 
    char * out = NULL; 
    int parts[16] = {1, 2, 05, 003}; 

    asprintf(&out, "%d.%d.%d.%d", parts[0], parts[1], parts[2], parts[3]); 

    return out; 
} 

int main(void) { 
    char * out = function(); 
    if (NULL != out) 
    { 
     printf("5s\n", out); 
     free(out); 
     out = NULL; 
    } 

    return 0; 
} 
5

看來你不太瞭解指針是什麼,局部變量,哪些分配內存一樣。

在您的function()中,您有一個變量out。你已經聲明它是一個字符指針。

您正在傳遞指向的變量asprintf()。這樣asprintf可以在堆上分配一些內存,並將該內存位置的地址存儲在out中。這就是所謂的「指針的指針」和爲什麼asprintf()簽名顯示爲asprintf(char **ret, ..) - 注意雙**

out現在包含已分配的內存地址。您然後離開function()out不再存在,因爲它是一個局部變量,只存在於堆棧上。之前包含在其中的地址已丟失,但在分配給堆地址的內存中仍然分配了內存......並且您有內存泄漏。

您需要free()內存之前,你失去了地址,它變得永遠超出你的範圍。