2014-09-23 90 views
0

由於我們不能釋放在函數中定義的本地指針「tmparr」,它會導致內存泄漏嗎?不知道這裏是否有更好的編碼解決方案。從函數返回數組會導致內存泄漏嗎?

我想傳遞一個函數指針,以便它將處理和更改函數內的數據。數據和值的大小可以在函數內靈活修改。

void printArray(int* data, 
       int length) 
{ 
    for (int i=0; i<length; i++) { 

     if ((i>0) && (i%5==0)) 
      printf("\n"); 

     printf("%d ", data[i]); 
    } 

    printf("\n\n"); 

} 

void copyPassPtrArray(int** data, 
         int length) 
{ 
    int* tmparr = (int*)malloc(length * sizeof(int)); 

    for (int i=0; i<length; i++) 
     tmparr[i] = i + 10; 

    *data = tmparr; 
} 


int main() 
{ 
    int length = 10; 

    int* ptrarr = (int*)malloc(length * sizeof(int)); 

    for (int i =0; i <length; i++) 
     ptrarr[i] = i; 

    printf("Origin ... \n"); 
    printArray(ptrarr, length); 

    copyPassPtrArray(&ptrarr, 20); 
    printf("After copyPassPtrArray ... \n"); 
    printArray(ptrarr, 20); 

    free(ptrarr); 

    return 0; 
} 

閱讀評論之後,我有以下提議的API解決方案。這種做法的目的是我們可能不知道函數中的某些計算後數組的大小和值是多少。它的「數據」需要返回到主或其他功能。但是,有沒有內存泄漏?

void copyGlobalPtrArray(int** data, 
         int length) 
{ 
    *data = (int*)malloc(length * sizeof(int)); 

    for (int i=0; i<length; i++) 
     (*data)[i] = i + 10; 
} 
+3

您分配了'ptrarr'內存的兩倍,並且免費只有一次;所以是的,這會導致內存泄漏。 (您也可以嘗試並測量它,例如使用valgrind)。 – Evert 2014-09-23 16:18:40

+0

*如果分配內存的函數未在該函數中釋放(通常不推薦),則從函數中返回該數據,以便在函數調用時指定一個明確的值。這使得它更清晰地釋放變量。 – Evert 2014-09-23 16:20:13

+0

太好了。你的反饋確實啓發了我。謝謝。 – Fusionmate 2014-09-23 16:58:57

回答

1

如果你是不是太確定是否已編寫的代碼是從內存泄漏問題解脫,那麼它的一個很好的做法是使用內存泄漏的工具

Valgrind是一個可以使用的工具。

下面

是命令:

valgrind --tool=memcheck --leak-check=full ./memleak (program name) 
==422== Command: ./memleak 
Origin ... 
0 1 2 3 4 
5 6 7 8 9 
After copyPassPtrArray ... 
10 11 12 13 14 
15 16 17 18 19 
20 21 22 23 24 
25 26 27 28 29 

==422== HEAP SUMMARY: 
==422==  in use at exit: 40 bytes in 1 blocks 
==422== total heap usage: 2 allocs, 1 frees, 120 bytes allocated // here total allocations n free done in ur code 

==422== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1 
==422== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==422== by 0x400767: main (memleak.c:35) //shows line number 

==422== LEAK SUMMARY: 
==422== definitely lost: 40 bytes in 1 blocks // here u can see memory leak 
==422== indirectly lost: 0 bytes in 0 block 
==422==  possibly lost: 0 bytes in 0 blocks 
==422== still reachable: 0 bytes in 0 blocks 
==422==   suppressed: 0 bytes in 0 blocks 

==422== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0) 

所以它能夠更好地運行這個並嘗試解決內存泄露自己

+0

已注意。我聽說過「valgrind」,會安裝並試用它。謝謝你教我 - 「如何釣魚」。讚賞。 – Fusionmate 2014-09-23 17:00:40

3

是的,有泄漏。 但它不是你認爲它的地方。

您正確free'd分配的區域爲copyPassPtrArray。 然而,原先分配的指針,

int* ptrarr = (int*)malloc(length * sizeof(int)); 

沒有被釋放。 那是因爲你在寫了原始數據的指針線

copyPassPtrArray(&ptrarr, 20); 

舊的指針永遠失去了! 相反,你應該存儲一個新的指針,並在結尾處釋放兩個指針。

例如

int main(){ 

    int length = 10; 

    int* ptrarr = (int*)malloc(length * sizeof(int); 
    int* copyarr; 

    for (int i =0; i <length; i++) 
     ptrarr[i] = i; 

    printf("Origin ... \n"); 
    printArray(ptrarr, length); 

    copyPassPtrArray(&copyarr, 20);  // put copied pointer into a separate variable 
    printf("After copyPassPtrArray ... \n"); 
    printArray(copyarr, 20); 

    free(ptrarr); 
    free(copyarr); 
    return 0; 
} 
+0

謝謝。在函數中傳遞「ptrarr」的目的是,函數可能需要引用計算值的數組,同時,它可以重寫值並在函數本身中調整數組的大小。最後,該函數重新使用內存緩衝區並返回主或其他功能。 – Fusionmate 2014-09-23 16:57:52

2

通常,在同一個函數內沒有釋放的函數內分配內存不是一個好主意。更好的是,爲函數外部的變量分配內存,將變量傳遞給函數,並將函數外部的變量釋放。

事情是這樣的:

void copyPassPtrArray(int *tmparr, int length) 
{ 
    for (int i=0; i<length; i++) 
     tmparr[i] = i + 10; 
} 


int main() 
{ 
    int length = 10; 
    int doublelength = 2 * length; 

    int* ptrarr = (int*)malloc(length * sizeof(int)); 
    int* newarr = (int*)malloc(doublelength * sizeof(int)); 

    for (int i =0; i <length; i++) 
     ptrarr[i] = i; 

    ... 

    copyPassPtrArray(newarr, doublelength); 

    ... 

    free(newarr); 
    free(ptrarr); 

    return 0; 
} 

如果你想分配內存的功能裏面,明確的變量返回的內存,並將其分配給一個(新的)變量。

那麼你的代碼可能是這樣的:

int *copyPassPtrArray(int length) 
{ 
    int* tmparr = (int*)malloc(length * sizeof(int)); 

    for (int i=0; i<length; i++) 
     tmparr[i] = i + 10; 

    return tmparr; 
} 


int main() 
{ 
    int length = 10; 

    int* ptrarr = (int*)malloc(length * sizeof(int)); 
    int* newarr = NULL; 

    for (int i =0; i <length; i++) 
     ptrarr[i] = i; 

    ... 

    newarr = copyPassPtrArray(20); 

    ... 

    free(newarr) 
    free(ptrarr); 

    return 0; 
} 

如果現在將有行ptrarr = copyPassPtrArray(20);相反,你會更容易注意到你重寫/重新分配ptrarr,因爲它在同一塊回顧早先分配。

+0

如果函數的任務是分配要在函數外部使用的內存,則不必在函數內釋放分配的內存。但是如果函數不需要返回額外分配的內存,那麼它確實負責釋放它分配的內容。 – 2014-09-23 17:33:54