Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 在**my_向量和***my_向量上应用free()的区别_C_Pointers - Fatal编程技术网

C 在**my_向量和***my_向量上应用free()的区别

C 在**my_向量和***my_向量上应用free()的区别,c,pointers,C,Pointers,我发现了一个释放矩阵内存的函数: void free_matrix(int ***matrix, int rows, int cols) { int row; if (matrix != NULL && *matrix != NULL) { for (row = 0; row < rows; row++) { free((*matrix)[row]); (*matrix)[row] = NUL

我发现了一个释放矩阵内存的函数:

void free_matrix(int ***matrix, int rows, int cols) {
    int row;

    if (matrix != NULL && *matrix != NULL) {
        for (row = 0; row < rows; row++) {
            free((*matrix)[row]);
            (*matrix)[row] = NULL;
        }
        free(*matrix);
        *matrix = NULL;
    }    
}
我不太明白为什么作者决定使用
***矩阵
而不是
**矩阵
,因为在我创建矩阵的其他方法中,他正是这样做的:

void fill_matrix(int **matrix, int rows, int cols) {
    int row = 0;
    int col = 0;

    for (row = 0; row < rows; row++) {
        for (col = 0; col < cols; col++) {
            matrix[row][col] = ((row + 1) * 10) + col;
        }
    }
}

int **create_matrix(int rows, int cols) {
    int row;
    int **matrix = malloc(rows * sizeof(int *));

    for (row = 0; row < rows; row++) {
        matrix[row] = malloc(cols * sizeof(int));
    }
    return matrix;
}
void fill_矩阵(整数**矩阵,整数行,整数列){
int行=0;
int col=0;
对于(行=0;行<行;行++){
for(col=0;col

作者突然决定使用
int***matrix
而不是
int**matrix

一定是有原因的。作者传递了矩阵指针的地址,以允许
自由矩阵
矩阵在调用者的作用域中将指针重置为
NULL
。一种预防措施是防止在释放矩阵数据后访问它,但是如果调用方复制了矩阵指针,它仍然可以通过副本访问它来调用未定义的行为

正如Olaf所建议的,矩阵应实现为2D数组,以便更简单地分配和释放:

/* allocating a pointer to a 2D array matrix[rows][cols] filled to 0 */
int (*matrix)[cols] = calloc(sizeof(*matrix), rows);
/* free the matrix */
free(matrix); matrix = NULL;
但是,如果大小不是恒定的,那么将这些矩阵作为函数参数传递或更糟的是返回它们所需的语法就不那么明显,需要一个C99兼容的编译器

为了澄清
***
方法的可疑优势,让我们看看更常见的双星解决方案:

void free_matrix(int **matrix, int rows, int cols) {
    int row;

    if (matrix != NULL) {
        for (row = 0; row < rows; row++) {
            free(matrix[row]);
        }
        free(matrix);
    }    
}

int main(void) {
    int **my_vector = create_matrix(5, 5);
    fill_matrix(my_vector, 5, 5);
    free_matrix(my_vector, 5, 5);
    if (my_vector) {
        /* trying to access the freed data will invoke undefined behavior */
    }
    return 0;
}
void free_矩阵(整数**矩阵,整数行,整数列){
int行;
if(矩阵!=NULL){
对于(行=0;行<行;行++){
自由(矩阵[行]);
}
自由(矩阵);
}    
}
内部主(空){
int**my_vector=创建_矩阵(5,5);
填充矩阵(我的向量,5,5);
自由_矩阵(我的_向量,5,5);
如果(我的_向量){
/*尝试访问释放的数据将调用未定义的行为*/
}
返回0;
}

在上面的代码中,
my_vector
不会被
free_matrix
重置为
NULL
,因此程序员可能会尝试访问它并调用未定义的行为(崩溃或任何其他),而在发布的代码中,三星
free\u matrix
会将
my\u vector
重置为
NULL
,这很容易测试。

int**
不能引用矩阵,也就是2D数组。身为C语言的三星程序员不是一种恭维。
int**
也不能引用矩阵。2D数组。@Olaf:您有点太挑剔了:
matrix
在C标准中没有定义为2D数组,使用单词matrix来表示实现同名数学对象的结构是合适的。编译时维数未知的矩阵在C89中不能实现为2D数组,但可以实现为指向单元格数组的指针数组,就像OP一样。对不起。如果我们使用参数
int**matrix
,是否无法通过
free(matrix)
将其释放?这看起来就像是在另一个身上做同样的事情way@DennisvonEich:您可以通过传递
矩阵
而不是
矩阵
来释放数据(假设您相应地更改
释放矩阵
),但后者确保调用方作用域中的变量
matrix
在其指向的数据被释放后自动设置为
NULL
。@chqrlie(以及任何偶尔的读者):我只是应用了一个简单的规则,始终使用
sizeof(*指针位于分配的左侧,用于分配malloc)
。不用进一步思考就行了。OTOH,
calloc
对两个参数都采用
size\t
。这是数组索引的正确类型,因此,如果您使用正确的类型,那么无论您如何组合条目的大小和数量,您都是安全的。
void free_matrix(int **matrix, int rows, int cols) {
    int row;

    if (matrix != NULL) {
        for (row = 0; row < rows; row++) {
            free(matrix[row]);
        }
        free(matrix);
    }    
}

int main(void) {
    int **my_vector = create_matrix(5, 5);
    fill_matrix(my_vector, 5, 5);
    free_matrix(my_vector, 5, 5);
    if (my_vector) {
        /* trying to access the freed data will invoke undefined behavior */
    }
    return 0;
}