2013-04-11 2 views
1

방금 ​​C 학습을 다시 시작했지만 실제로 일부 메모리 관리 세부 정보와 혼동합니다. 나는 아래의 코드 트랩C malloc 오류 구조 해제

중단 ... 해제되지

포인터가 할당되지 않은 얻고있다. 정말로은 malloc 당 1 개의 무료가 필요합니까? 왜 내 코드가 잘못 되었나요?
감사합니다.

#define N 9 

typedef struct 
{ 
    int MAX_LIST_SIZE; 
    int length; 
    int *ini; 
}List; 

/* allocates new List and its data */ 
List *newList(int size) 
{ 
    List *list = malloc(sizeof(List)); 
    list->MAX_LIST_SIZE = size; 
    list->length = 0; 
    list->ini = malloc(sizeof(int) * size); 

    return list; 
} 

/* add some value to the list */ 
void addList(List *list, int val) 
{ 
    if (list->length < list->MAX_LIST_SIZE) 
     list->ini[list->length++] = val; 
    else 
     fprintf(stderr, "Error: add(): List is full.\n"); 
} 

/* get an array of N*N lists malloc-ed Lists */ 
List *gridList() 
{ 
    int i, j; 
    List *cells = malloc(sizeof(List) * N * N); 

    for (i = 0; i < N * N; i++) 
    { 
     /* malloc is called inside NewList()*/ 
     cells[i] = *newList(N); 
     for (j = 0; j < N; j++) 
      addList(&cells[i], j + 1); 
    } 

    return cells; 
} 


/* inside main */ 
List *cells = gridList(); 

/* use cells ... */ 

/* free */ 
for (i = 0; i < N * N; i++) 
{ 
    free(cells[i].ini); 
    /* line below causes CRASH */ 
    free(&cells[i]); 
} 
+0

1) 코드) 2 '완료'일 필요는 없습니다 :

마지막에 무료로 문을 변경? 3) Java가 있습니다. – Fernando

+1

C는 훌륭한 언어입니다. 그러나 작고 완전한 @ compileable example에 대한 @ Beta의 요점은 우수합니다. 당신이 충고를 따르면 대답을 얻을 가능성이 더 큽니다. – Gene

+0

@ 베타 : 1 점과 2 점이 매우 좋습니다. 포인트 3은 언어 전쟁의 장소가 아닙니다. –

답변

1

당신은 할 동적으로 newList에 의해 할당 된 목록의 사본에 cells의 각 요소를 설정

cells[i] = *newList(N); 

. 따라서 newList은 동적으로 목록을 할당 한 다음 동적으로 할당 된 List에 대한 포인터를 가져 와서 참조를 취소하고 cells[i]에 복사합니다. 그럼 나중에 free()에 각 요소를 이동하는 경우에 :

free(&cells[i]); 

cells[i]의 각 요소는 List 아닌 List * (목록 포인터)이기 때문에 작동하지 않습니다 malloc()에 의해 할당.

두 가지 옵션이 있습니다. 1 개 (나쁜 것)는 아무 것도 없기 때문에 마지막으로 free() 행을 삭제하는 것입니다. 그러나 이것은 단지 큰 문제를 다루고 있는데, 이것은 메모리 누수가 있다는 것입니다. 왜냐하면 여러분은 되돌아 가서 동적으로 할당 된 ListnewList()으로 할당 해제 할 수 없기 때문입니다.

List **cells = malloc(sizeof(List*) * N * N); 

그래서 그 cells[i]List *을 의미한다 :

대신 당신이 당신이 그것을 변경 할 수있는 목록에 대한 포인터의 배열을 할 가능성이 높습니다. 당신은 단순히에 행을 변경해 줄 수 있도록

cells[i] = newList(N); 

유사, addList()는, 이러한 포인터를 취합니다 : 당신이 라인을 변경 할 수 있도록 포인터 newList() 반환 등,

addList(cells[i], j + 1); 

&cells[i] 경과 한 것 그것은 당신이 원하는 것이 아닌 포인터의 주소입니다.

free(cells[i]->ini); // ->init because cells[i] is now a pointer to a List, List * 
free(cells[i]); 
+0

내가 얻지 못한 '복사'문제. newPoint() 함수는 'p1'을 가리키는 List *를 반환합니다. 당신은 세포가 [i] = * newPoint()를 할 경우 & cells [i]이 'p1'을 가리 키지 않는다고 말하고 있습니까? – Fernando

+0

'newList()'실제로'malloc()'을 가리키는'List *'를 반환합니다'List' ('p1'이 무엇을 의미하는지 모르겠습니다). 그런 다음'cells [i] = * newList()'를 실행하면 * newList() 부분의 별표 (*)가 해당 포인터를 역 참조하므로 포인터가 아닌 실제'List'를 얻을 수 있습니다. 'cells [i]'는'List'를 참조하기 때문에 오른쪽에있는'List' ('* newList()')를 왼쪽의'List' ('cells [i]')에 복사합니다. 그것이 C로 처리되는 방식이기 때문에 복사됩니다. 여러분의 의견에 따라'cells [i] = * newList()','cells [i]'는 아무 것도 가리 키지 않습니다. List '(반환 된 사람의 사본). –

+0

정수를 malloc()했을 경우와 같이 생각해보십시오. 'int * someInt = malloc (sizeof (int));'. 여기서'someInt'는 정수 자체가 아닌'malloc()'에 대한 포인터입니다. 그래서 당신은'int * aPointer = someInt'를 할 수 있습니다. 그러나, 당신의 경우,'cells [i]'는'List' ('List *')에 대한 포인터를 가지고 있지 않습니다. 대신에'List' 자체에 대한 포인터를 가지고 있습니다. 그래서 당신은 우선 그것을 역 참조했습니다. 그래서이 예제에서,'int aCopy = * someInt;'. –

0

목록의 배열을 할당하고 목록의 전체 내용을 배열 요소에 복사 한 다음 문제를 해결하는 것이 문제입니다. 원래 할당 된 List 레코드는 메모리 누수이며 무료 호출은 실제로 malloc으로 처리되지 않은 메모리를 해제하려고 시도합니다 (또는 더 정확하게 하나의 큰 블록에서 malloc으로 처리되었습니다).

당신은 당신의 목록을 유지하는 포인터에 대한 포인터의 배열을 원하는 :

/* get an array of N*N lists malloc-ed Lists */ 
List **gridList() 
{ 
    int i, j; 
    // VV note change here 
    List **cells = malloc(sizeof(List*) * N * N); 

    for (i = 0; i < N * N; i++) 
    { 
     /* malloc is called inside NewList()*/ 
     cells[i] = newList(N); // << Note change here. 
     for (j = 0; j < N; j++) 
      addList(cells[i], j + 1); 
    } 
    return cells; 
} 

/* free */ 
for (i = 0; i < N * N; i++) 
{ 
    free(cells[i]->ini); // << and here 
    /* line below causes CRASH */ 
    free(cells[i]); // << and here 
} 
free(cells); 
+0

감사합니다. 작동합니다! – Fernando