2017-11-12 1 views
2

이 코드에서는 Python 목록이나 Java ArrayList와 비슷한 목록 컬렉션을 구현하는 C 모듈을 개발하려고합니다. 그러나 나는 다음에 문제가있어,목록에 할당 된 메모리를 해제하지 않고 매개 변수가 가리키는 목록을 비우는 방법은 무엇입니까?

#include <assert.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <stdbool.h>` 

#include "array_list.h" 

/* Construct a new, empty list, and return a pointer to it 
* Parameter capacity is the # of elements that can be stored in the list. 
* Terminate the program via assert if capacity is <= 0. 
* Terminate the program via assert if memory for the list cannot be 
* allocated from the heap. 
*/ 

intlist_t *intlist_construct(int capacity) 
{ 
    int *pa; 
    pa = malloc(capacity * sizeof(int)); 
    assert(pa != NULL); 

    intlist_t *list = malloc(sizeof(intlist_t)); 
    assert(list != NULL); 

    list->capacity = capacity; 
    list->size = 0; 
    list->elems = pa; 

    return list; 
} 

/* Destroy the list pointed to by parameter list, deallocating all memory 
* that was allocated from the heap. 
* Terminate the program via assert if list is NULL. 
*/ 

void intlist_destroy(intlist_t *list) 
{ 
    assert(list != NULL); 
    free(list->elems); /* Return the array to the heap. */ 
    free(list); /* Return the structure to the heap. */ 
} 

/* Print the list pointed to by parameter list to the console. 
* Terminate the program via assert if list is NULL. 
*/ 

void intlist_print(const intlist_t *list) 
{ 
    assert(list != NULL); 

    if (list->size == 0) 
    { 
     printf("[]\n"); 
    } 

    printf("["); 

    for (int i = 0; i < list->size; i++) 
    { 
     if (i != list->size - 1) 
     { 
      printf("%d ", list->elems[i]); 
     } 
     else 
     { 
      printf("%d]", list->elems[i]); 
     } 
    } 
} 

/* Insert element at the end of the list pointed to by list. 
* Return true if element is appended; otherwise return false 
* (which indicates that the list is full.) 
* Terminate the program via assert if list is NULL. 
*/ 

_Bool intlist_append(intlist_t *list, int element) 
{ 
    assert(list != NULL); 

    if (list->size < list->capacity) 
    { 
     list->elems[list->size] = element; 
     list->size++; 
     return true; 
    } 
    else 
    { 
     return false; 
    } 
} 

/* Return the maximum number of integers that can be stored in the list 
* pointed to by parameter list. 
* Terminate the program via assert if list is NULL. 
*/ 

int intlist_capacity(const intlist_t *list) 
{ 
    assert(list != NULL); 
    return list->capacity; 
} 

/* Return the number of integers in the list pointed to by parameter list. 
* Terminate the program via assert if list is NULL. 
*/ 
int intlist_size(const intlist_t *list) 
{ 
    assert(list != NULL); 
    return list->size; 
} 

/* Return the element located at the specified index, in the list 
* pointed to by parameter list. 
* Terminate the program via assert if list is NULL, 
* or if index is not in the range 0 .. intlist_size() - 1. 
*/ 

int intlist_get(const intlist_t *list, int index) 
{ 
    assert(list != NULL); 
    return list->elems[index]; 
} 

/* Store element at the specified index, in the list pointed to by 
* parameter list. Return the integer that was previously 
* stored at that index. 
* Terminate the program via assert if list is NULL, 
* or if index is not in the range 0 .. intlist_size() - 1. 
*/ 
int intlist_set(intlist_t *list, int index, int element) 
{ 
    assert(list != NULL); 

    int previous; 
    previous = list->elems[index]; 
    list->elems[index] = element; 

    return previous; 
} 

내 코드의 시작 부분은 작동이 내가 생성 한 코드가

typedef struct { 
int *elems; // Pointer to backing array. 
int capacity; // Maximum number of elements in the list. 
int size;  // Current number of elements in the list. 
} intlist_t; 

:

이 구조체 intlist_t있다 . intlist_removal이 반환 될 때 0 개의 정수를 포함하는 목록을 반환하고 싶습니다. 목록을 비울 때 제대로 작동하지 않습니다. 코드에서

/* Empty the list pointed to by parameter list. 
* Memory allocated to the list is not freed, so the emptied list can 
* continue to be used. 
* Terminate the program via assert if list is NULL. 
*/ 

void intlist_removeall(intlist_t *list) 
{ 
    assert(list != NULL); 
    free(list); 
} 
+0

왜 제대로 작동하지 않는지 더 설명 할 수 있습니까? – Grantly

+0

내가 입력 할 때 : list = intlist_construct (10); 그래서 용량은 10이고 목록을 [0, 2, 4, 6, 8]로 초기화합니다. intlist_removeall (list)를 호출하면 결과는 0이어야합니다. 메모리 – student17

+0

게시물을 추가 정보로 편집하십시오 – Grantly

답변

2

살펴 보자 : 이제

void intlist_removeall(intlist_t *list) 
{ 
    assert(list != NULL); 
    free(list); 
} 

, 스스로에게 물어 "나는 intlist 개체를 만들 않았다 어떤 변화?"

내가 앉아있는 곳에서 표준 assert과 표준 free (작성한 사용자 지정 함수와 반대)을 사용한다고 가정하면 아무 것도하지 않은 것입니다.

크기를 업데이트 했습니까? 번호 :

용량을 업데이트 했습니까? 번호

개별 요소를 0과 같은 알려진 시작 값으로 재설정 했습니까? 제

당신이 한 유일한 것은 당신이 특정 블록을 사용하여 수행하는 메모리 할당 서브 시스템을 알려줍니다 free(list)를 호출하는 것입니다 (assert 이후 컴파일러 스위치에 따라 밖으로 ifdef'ed # 될 것입니다).

다중 스레드 환경에있는 경우 다른 스레드가 free 호출과 intlist_removeall에서 호출하는 사이에 목록 데이터 구조에 쓸 수 있습니다. 그렇지 않으면 방금 할당 추적 데이터를 업데이트하고 프로그램에 충돌을 일으킬 수있는 나중에 언젠가 나중에 재사용 될 수있는 매달린 포인터를 만듭니다.

자신에게 물어보십시오 : 요소가 제거되었다는 것을 "기록"하고 싶다면 어떻게해야합니까?

크기 요소를 업데이트하고 모든 "애프터"요소를 앞으로 이동하여 갭을 충당 할 것으로 예상됩니다.

removeall의 경우에도 비슷한 작업을해야합니다. 단, 크기가 0으로 내려 가고 요소가 남아 있지 않기 때문에 조금 쉽습니다.

또한 removeall은 (은) destroy과 비교하면 어떻습니까? 왜 구조를 자유롭게하고 있니? 파이썬에서 길이가 0 인리스트는 여전히 목록입니다. None 또는 undef 또는 그 외의 것이 없습니다.

intlist_t * list1 = NULL; 
intlist_t * list2 = intlist_construct(10); 

이 두 가지의 차이점은 무엇입니까?

0

remove_allfree(list);으로 전화하면 목록에 대한 포인터가 해제됩니다. 이 작업은 원하는 작업을 수행하지 못하며 나중에 list->elems*을 해제하지 않아 나중에 런타임 오류가 발생합니다. 데이터 구조가 어떻게 작동하는지 기대해야합니다. 메모리를 전혀 비우지 않고도 원하는 것을 수행 할 수 있습니다.

크기 변수로 간단하게 작업 할 수 있습니다.

관련 문제