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*/
}

2 ответа

Ты звонишь free_matrix дважды за a и дважды за b, За a сначала вы выделяете память, а затем освобождаете ее, в этом порядке вы выполняете эти операции дважды; однако для b Вы выделяете, затем освобождаете, а затем, не выделяя снова, вы пытаетесь освободить, что приводит к сбою.

призвание free для освобождения выделенной памяти не устанавливает указатель на нее NULL, это должно быть сделано вручную. Без этого указатель становится висящим указателем, т. Е. Указателем, указывающим на какое-то место, недоступное процессу для чтения. Чтобы избежать этого, весьма обычно иметь вспомогательную функцию для освобождения памяти и установки указателя на NULL,

void free_data(void **pp)
{
    if (pp && *pp)
    {
       free(*pp);
       *pp = NULL;
    }
}

Хотя вполне допустимо проверять, является ли указатель ненулевым, разыменование - это неопределенное поведение (UB) с точки зрения языка. призвание free попросит библиотеку времени выполнения C попытаться сделать это, тем самым вы войдете в UB land согласно спецификации языка; Что касается среды выполнения C, он будет пытаться получить доступ к памяти, которая больше не принадлежит процессу, и, таким образом, аварийно завершится, поскольку операционная система вызовет ошибку отказа в доступе в какой-либо форме, например, Linux вызовет эту (среди прочих) ошибку сегментации, а Windows - допустим нарушение доступа.

Кроме того, некоторые утверждают, что установка освобожденного указателя на NULL это не очень хорошая практика, так как она маскирует ошибки двойного удаления от обнаружения. Скажем, вы установили освобожденный указатель на NULL и в другом месте вы звоните free с тем же указателем т.е. вы бы по существу позвонить free(NULL);, Это допустимый параметр для передачи free и это ничего не даст, тем самым не зная, что даст миру понять, что двойное удаление только что произошло. Если бы не было установлено NULLВторой звонок free вызовет ошибку нарушения доступа при попытке освободить уже освобожденное местоположение и тем самым приведет к известной ошибке двойного удаления.

free() не устанавливает указатель на NULL. Вы должны сделать это самостоятельно.

Другие вопросы по тегам