2014-09-23 1 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

자신을 누설; 그래서 네, 이것은 메모리 누수를 초래할 것입니다. (valgrind를 사용하여 시도해보고 측정 할 수도 있습니다.) – Evert

+0

* 해당 함수에서 해제되지 않은 함수에 메모리를 할당하는 경우 (일반적으로 권장하지 않음) 함수에서 해당 데이터를 반환하므로 함수 호출 시점에 할당 할 명시 적 값을 갖습니다. 따라서 변수를 없앨 수 있습니다. – Evert

+0

좋아요. 당신의 피드백은 분명히 나를 깨우쳐주었습니다. 고맙습니다. – Fusionmate

답변

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) 

그래서 그것의 더 나은이를 실행하고 해결하기 위해 시도하는 메모리가 두 번 ptrarr``에 대한 메모리를 할당하고 무료 한 번만

+0

Noted. 나는 "valgrind"에 대해 들어서 설치하고 시도해 볼 것입니다. 저를 가르쳐 주셔서 감사합니다 - "낚시하는 법". 감사합니다. – Fusionmate

3

예 누수가 있습니다. 그러나 그것이 당신이 생각하는 곳이 아닙니다.

copyPassPtrArray에 할당 된 영역이 정확히 free입니다. 그러나, 원래 할당 된 포인터,

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

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

함수의 작업이 함수 외부에서 사용할 메모리를 할당하는 것이면 함수 내에 할당 된 메모리를 해제 할 필요가 없습니다. 그러나 함수가 여분의 할당 된 메모리를 반환 할 필요가 없다면 실제로 할당 된 것을 해제해야합니다. –

관련 문제