2014-10-20 3 views
-1

내 구조체를 해제하는 방법을 작성했습니다. 이제 문제가 생겼어. 이 메서드를 두 번 호출하면 오류가 발생합니다. 하지만 구조체에 무언가가 있는지 확인하여 오류가 발생하는 이유를 모른다.C freeing check가 작동하지 않습니다.

내 구조체 :

typedef struct { 
    int num_rows; 
    int num_cols; 
    int** data; 
} matrix; 

내 무료 방법 :

void free_matrix(matrix* m){ 
    int i; 
    for(i=0;i<m->num_rows;i++){ 
     if(m->data[i]!=NULL){ 
      free(m->data[i]); 
     } 
    } 
    if(m->data!=NULL){ 
     free(m->data); 
    } 
} 

추가 방법 :

void fill_matrix_a(matrix* m){ 
    m->data[0][0] = 1; 
    m->data[0][1] = 0; 
    m->data[0][2] = 2; 
    m->data[1][0] = 0; 
    m->data[1][1] = 3; 
    m->data[1][2] = 1; 
} 

void fill_matrix_b(matrix* m){ 
    m->data[0][0] = 0; 
    m->data[0][1] = 3; 
    m->data[1][0] = 2; 
    m->data[1][1] = 1; 
    m->data[2][0] = 0; 
    m->data[2][1] = 4; 
} 

void init_matrix(matrix* m, int num_rows, int num_cols){ 
    int i; 
    m->num_cols = num_cols; 
    m->num_rows = num_rows; 
    m->data = (int**) calloc(num_rows,sizeof(int*)); 
    if(m->data==NULL){ 
     printf("%s\n", "ERROR: probleem bij geheugenallocatie."); 
     exit(1); 
    } 
    for(i=0;i<num_rows;i++){ 
     m->data[i] = (int*) calloc(num_cols,sizeof(int)); 
     if(m->data[i]==NULL){   /* THE PROGRAM SAYS THIS IS TRUE BUT IT ISN'T BECAUSE I ALREADY FREED THE DATA OF B!! */ 
      printf("%s\n", "ERROR: probleem bij geheugenallocatie."); 
      exit(1); 
     } 
    } 
} 

나에게 오류 제공에있어서

void ex_1_matrix_operations(){ 
    matrix a,b,c; 

    /* init a(2,3) and fill with elements */ 
    init_matrix(&a,2,3); 
    fill_matrix_a(&a); 
    print_matrix(&a); 

    /* init b (default) and fill with elements */ 
    init_matrix_default(&b); 
    fill_matrix_b(&b); 
    print_matrix(&b); 
    free_matrix(&a); 
    free_matrix(&b); 

    /* create unity matrix */ 
    init_identity_matrix(&a,2); 
    print_matrix(&a); 
    free_matrix(&a); 
    free_matrix(&b); /* THIS IS WHERE MY ERROR OCCURS*/ 
} 
+3

작동하지 않는 기능은 무엇입니까? 어떤 오류가 발생합니까? –

+4

free()는 포인터를 NULL로 설정하지 않습니다. 직접 처리해야하지만, 그 점을 추측하면됩니다. –

+0

'matrix_b'를 두 번 해제했습니다. –

답변

2

free()는 NULL에 대한 포인터를 설정하지 않습니다. 너 스스로 그렇게해야 해.

9

a의 경우 두 번, b의 경우 두 번을 free_matrix (으)로 두 번 호출합니다. a의 경우 먼저 메모리를 할당 한 다음 해제하고 이러한 순서로 두 번 작업을 수행하십시오. 그러나 b에 대해 할당 한 다음 해제 한 다음 다시 할당하지 않으면 해제하려고 시도합니다. 이로 인해 충돌이 발생합니다.

할당 된 메모리를 해제하기 위해 free을 호출하면이를 가리키는 포인터를 NULL으로 설정하지 않습니다. 수동으로 수행해야합니다. 이렇게하지 않으면, 포인터는 dangling pointer, 즉 프로세스에 의해 판독 가능하지 않은 (액세스 가능한) 일부 위치를 가리키는 포인터가된다. 그래서 이것을 피하기 위해 메모리를 비우고 포인터를 NULL으로 설정하는 도우미 함수를 갖는 것은 드문 일이 아닙니다. 포인터는 언어의 관점에서 정의되지 않은 동작 (UB)는 역 참조, null가 아닌 경우 확인하기 위해 완벽하게 유효한 비록

. free을 호출하면 C 런타임 라이브러리가이를 시도하게되므로 언어 ​​사양에 따라 UB 랜드를 입력하게됩니다. C 런타임의 경우 프로세스에서 더 이상 소유하지 않는 메모리에 액세스하려고 시도하므로 운영 체제가 액세스 거부 오류를 발생시키는 등의 오류가 발생합니다. 리눅스는 Segmentation Fault이라고하며, Windows는 이라는 액세스 위반이라고합니다..

다른 말로하면 해제 된 포인터를 NULL으로 설정하면 이중 삭제 버그가 발견되는 것을 숨기므로 좋은 방법이 아니라고 주장합니다. 해제 된 포인터를 NULL으로 설정하고 다른 포인터를 free이라고하고 동일한 포인터 (예 : free(NULL);)를 호출한다고 가정 해 보겠습니다. 이것은 free에 전달할 수있는 유효한 매개 변수이며 아무것도하지 않으므로 이중 삭제가 방금 발생했다는 사실을 세상에 알려주지 못합니다. NULL으로 설정하지 않은 경우 free에 대한 두 번째 호출은 이미 해제 된 위치를 해제하려고 시도 할 때 액세스 위반 오류를 발생시켜 이중 삭제 버그를 알 수있게합니다.

+0

OK, 많이 감사합니다. – user3371198

관련 문제