2014-10-20 34 views
-1

我寫了一個方法來釋放我的結構。現在我有一個問題。當我調用這個方法兩次時,它給了我一個錯誤。但是我確實檢查了我的結構中是否有東西,所以我不知道它是如何給我帶來錯誤的。C釋放檢查不起作用

我的結構:

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

什麼不行?你會得到什麼錯誤? – 2014-10-20 13:34:45

+4

free()不會將指針設置爲NULL,您必須自己動手,但只是猜測這是您的問題... – 2014-10-20 13:36:02

+0

您正在釋放'matrix_b'兩次。 – 2014-10-20 13:36:07

回答

2

free()不會將指針設置爲NULL。你需要自己做。

9

您打給free_matrix兩次,a兩次,b兩次。對於a,你先分配內存然後釋放內存,依次執行這些操作兩次;然而,對於b,您分配了然後釋放,然後再次分配,您嘗試釋放,導致崩潰。

調用free釋放分配的內存,不會將指向它的指針設置爲NULL,這必須手動完成。如果不這樣做,指針變爲dangling pointer,即指向某個位置的指針,該位置對於該進程不可讀(可訪問)。爲了避免這種情況,有一個輔助函數來釋放內存並將指針設置爲NULL並不罕見。

雖然這是完全有效的檢查,如果指針非空,解引用是從語言的角度來看未定義行爲(UB)。調用free會要求C運行時庫試圖做到這一點,從而按照語言規範輸入UB域;對於C運行時,它將嘗試訪問不再由進程擁有的內存,並因此而崩潰,因爲操作系統會引起某種形式的訪問被拒絕錯誤,例如, Linux會稱之爲(除其他外)Segmentation Fault,而Windows會說訪問衝突

另外,有人認爲將釋放的指針設置爲NULL並不是一個好的做法,因爲它掩蓋了雙重刪除錯誤的發現。假設您將釋放的指針設置爲NULL,並在其他地方使用相同的指針調用free,即您基本上將調用free(NULL);。這是傳遞給free的有效參數,它什麼也不做,因此永遠不會知道讓世界知道雙刪除剛剛發生。如果未設置爲NULL,則在嘗試釋放已釋放的位置時,第二次撥打free會引發訪問衝突錯誤,從而導致發生雙重刪除錯誤。

+0

好的,非常感謝 – user3371198 2014-10-20 13:39:26