C免费检查不起作用

use*_*198 -1 c free dynamic-memory-allocation dangling-pointer

我写了一个方法来释放我的结构.现在我有一个问题.当我两次调用此方法时,它会给我一个错误.但我确实检查我的结构中是否有某些东西,所以我不知道它是如何可能给我错误的.

我的结构:

typedef struct {
    int num_rows;
    int num_cols;
    int** data;
} matrix;
Run Code Online (Sandbox Code Playgroud)

我的免费方法:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

额外方法:

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

给我一个错误的方法:

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*/
}
Run Code Online (Sandbox Code Playgroud)

leg*_*s2k 9

你打free_matrix两次电话a和两次电话b.对于a你第一次分配内存,然后释放它,因为为了你做这些操作两次; 但是,为了b你分配然后释放然后再没有分配,你试图释放,这导致崩溃.

调用free释放分配的内存,不设置指向它的指针NULL,这必须手动完成.在不这样做的情况下,指针变为悬空指针,即指向某个位置的指针,该指针不被进程读取(可访问).为了避免这种情况,有一个辅助函数释放内存并将指针设置为常量并不罕见NULL.

void free_data(void **pp)
{
    if (pp && *pp)
    {
       free(*pp);
       *pp = NULL;
    }
}
Run Code Online (Sandbox Code Playgroud)

虽然检查指针是否为非空是完全有效的,但从语言的角度来看,取消引用它是未定义的行为(UB).调用free会要求C运行时库尝试这样做,从而根据语言规范输入UB land; 对于C运行时,它将尝试访问不再由进程拥有的内存,因此崩溃,因为操作系统会引发某种形式的访问被拒绝错误,例如Linux将调用此(以及其他)分段错误,而Windows将说访问冲突.

顺便说一下,有些人认为设置一个释放指针NULL并不是一个好习惯,因为它掩盖了双重删除错误.假设您将释放的指针设置为NULLfree使用相同指针调用的其他位置,即基本上您将调用free(NULL);.这是一个传递给free它的有效参数,它不会做任何事情,因此从不知道让世界知道双重删除刚刚发生.如果没有设置NULL,第二次调用free会在尝试释放已经释放的位置时引发访问冲突错误,从而导致双删除错误.