6

我在不产生内存泄漏的情况下生成 int 矩阵时遇到了一些问题。我希望能够通过 read_matrix() 将给定的(全局)矩阵动态地制成任何大小。但是我希望以后能够释放内存。所以在我的主要方法中,第二个 printf 应该导致总线错误,因为它不应该分配任何内存。我将如何去创造这个?

int**       first_matrix;
int**       second_matrix;
int**       result_matrix;

int** read_matrix(int size_x, int size_y)
{
    int** matrix;
    matrix = calloc(size_x, sizeof(int*));
    for(int i = 0;i<size_x;i++) {
        matrix[i] = calloc(size_y, sizeof(int));
    }
    for(int i = 0;i<size_x;i++) {
        for(int j = 0;j<size_y;j++) {
            matrix[i][j] = i*10+j;
        }
    }
    return matrix;
}

int main(int stackc, char** stack)
{
    first_matrix = read_matrix(10,10);
    printf("9:3 %d - 4:6 %d \n", first_matrix[9][3], first_matrix[4][6]);
    free(*first_matrix);
    free(first_matrix);
    printf("9:3 %d - 4:6 %d \n", first_matrix[9][3], first_matrix[4][6]);
}
4

7 回答 7

9

仅仅因为内存已被释放并不意味着您无法访问它!当然,在它被释放后访问它是一个非常糟糕的主意,但这就是它在您的示例中起作用的原因。

请注意,free( *first_matrix )只有 free's first_matrix[0],而不是其他数组。您可能需要某种标记来表示最后一个数组(除非您总是知道释放外部数组时分配了多少内部数组)。就像是:

int** read_matrix(int size_x, int size_y)
{
    int** matrix;
    matrix = calloc(size_x, 1+sizeof(int*)); // alloc one extra ptr
    for(int i = 0;i<size_x;i++) {
        matrix[i] = calloc(size_y, sizeof(int));
    }
    matrix[size_x] = NULL; // set the extra ptr to NULL
    for(int i = 0;i<size_x;i++) {
        for(int j = 0;j<size_y;j++) {
            matrix[i][j] = i*10+j;
        }
    }
    return matrix;
}

然后当你释放它们时:

// keep looping until you find the NULL one
for( int i=0; first_matrix[i] != NULL; i++ ) {
    free( first_matrix[i] );
}
free( first_matrix );
于 2008-09-19T21:18:00.320 回答
2

您需要单独释放每一行:


void free_matrix(int **matrix, int size_x)
{
    for(int i = 0; i < size_x; i++)
        free(matrix[i]);
    free(matrix);
}
于 2008-09-19T21:14:08.177 回答
1

释放内存并不会让它消失,它只是意味着另一个分配可能会占用相同的内存块。无论您放入什么,它都会一直存在,直到有其他东西覆盖它。

此外,您并没有释放您分配的所有内容。您只释放指针数组和第一行。但即使你正确地释放了所有东西,你仍然会有同样的效果。

如果要创建“总线错误”,则需要指向不属于您的进程的内存。你为什么要这样做呢?

于 2008-09-19T21:15:21.997 回答
0

您只释放了 first_matrix 的第一行(或列)。编写另一个这样的函数:

void free_matrix(int **matrix, int rows)
{
    int i;
    for(i=0; i<rows; i++)
    {
        free(matrix[i]);
    }
    free(matrix);
}

您可能希望将矩阵制作成一个结构来存储它的行数和列数。

于 2008-09-19T21:14:59.923 回答
0

我建议使用 valgrind 来追踪未释放的内存,而不是试图让总线错误发生。它也适用于许多其他东西。

山姆

于 2008-09-19T21:15:28.797 回答
0

您正在获得内存泄漏,因为您正在释放矩阵的第一行和行列表,但没有释放第 1 到第 n 行。您需要循环调用 free 。

但是,有几种选择: - 分配 sizeof(int*) rows + rows cols*sizeof(int) 字节并将第一个字节用作行指针。这样,您只有一块内存可以释放(并且在分配器上也更容易) - 使用包含行数的结构。然后你可以完全避免行列表(节省内存)。唯一的缺点是您必须使用函数、宏或一些杂乱的符号来处理矩阵。

如果你选择第二个选项,你可以在任何 C99 编译器中使用这样的结构,并且只需要分配一个内存块(大小为 numints*sizeof(int)+sizeof(int)):

struct matrix {
    int rows;
    int data[0];
}
于 2008-09-19T21:16:57.047 回答
0

您在这里缺少的概念是,对于每个 calloc,都必须有一个 free。并且该 free 必须应用于从 calloc 传回的指针。

我建议您创建一个函数(名为 delete_matrix),它使用循环来释放您在此处分配的所有指针

for(int i = 0;i < size_x;i++) { matrix[i] = calloc(size_y, sizeof(int)); }

然后,一旦完成,释放 this 分配的指针。

矩阵 = calloc(size_x, sizeof(int*));

你现在的做法,

免费(*first_matrix);免费(first_matrix);

不会做你想做的事。

于 2008-09-19T21:21:08.753 回答