带有指针的int矩阵 - 内存分配混乱

时间:2021-11-01 05:58:07

I'm having some issues with producing an int matrix without creating memory leaks. I want to be able to make a given (global) matrix into any size dynamically via read_matrix(). But then i want to be able to free the memory later on. So in my main method the second printf should result in a bus error since it should not have any memory allocated to it. How would i go about creating this?

我在生成int矩阵时遇到了一些问题而没有产生内存泄漏。我希望能够通过read_matrix()动态地将给定(全局)矩阵制作成任意大小。但后来我希望能够在以后释放内存。所以在我的main方法中,第二个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]);
}

7 个解决方案

#1


9  

Just because the memory has been free'd doesn't mean you can't access it! Of course, it's a very bad idea to access it after it's been free'd, but that's why it works in your example.

仅仅因为内存已经免费并不意味着你无法访问它!当然,在它被免费后访问它是一个非常糟糕的主意,但这就是为什么它适用于你的例子。

Note that free( *first_matrix ) only free's first_matrix[0], not the other arrays. You probably want some kind of marker to signify the last array (unless you will always know when you free the outer array how many inner arrays you allocated). Something like:

注意free(* first_matrix)只有free的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;
}

Then when you're freeing them:

然后当你释放它们时:

// keep looping until you find the NULL one
for( int i=0; first_matrix[i] != NULL; i++ ) {
    free( first_matrix[i] );
}
free( first_matrix );

#2


2  

You need to free each row individually:

您需要单独释放每一行:


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

#3


1  

Freeing the memory doesn't make it go away, it just means that another allocation might grab that same chunk of memory. Whatever you put in it will still be there until something else overwrites it.

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

Also, you're not freeing everything you allocated. You're only freeing the array of pointers and the first row. But even if you free everything correctly, you would still have the same effect.

此外,你没有释放你分配的一切。你只是释放了指针数组和第一行。但即使你正确地释放了一切,你仍然会有同样的效果。

If you want to create a "bus error" you need to point to memory that doesn't belong to your process. Why do you want to do that anyway?

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

#4


0  

You only freed the first row (or column) of first_matrix. Write another function like this:

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

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

You might want to make the matrix into a struct to store it's row and column count.

您可能希望将矩阵转换为结构以存储其行和列数。

#5


0  

I recommend using valgrind to track down unfree'd memory, as opposed to trying to make a bus error occur. It rocks for lots of other stuff as well.

我建议使用valgrind来追踪不*的内存,而不是试图发生总线错误。它还有许多其他东西。

Sam

#6


0  

You're getting memory leaks because you're freeing the first row of the matrix and the list of rows, but none of the 1 to nth rows. You need to call free in a loop.

您正在获得内存泄漏,因为您释放了矩阵的第一行和行列表,但没有释放第1行到第n行。你需要循环免费呼叫。

There are a couple of alternatives, however: - Allocate sizeof(int*)rows + rowscols*sizeof(int) bytes and use the first bytes for the row pointers. That way, you only have a single chunk of memory to free (and it's easier on the allocator, too) - Use a struct that contains the number of rows. Then you can avoid the row list altogether (saving memory). The only downside is that you have to use a function, a macro, or some messy notation to address the matrix.

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

If you go with the second option, you can use a struct like this in any C99 compiler, and again only have to allocate a single block of memory (of size numints*sizeof(int)+sizeof(int)):

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

struct matrix {
    int rows;
    int data[0];
}

#7


0  

The concept you are missing here, is that for every calloc, there must be a free. and that free must be applied to the pointer passed back from calloc.

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

I recommend you create a function (named delete_matrix) that uses a loop to free all of the pointers that you allocate in here

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

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

for(int i = 0; i ;>

then, once that is done, free the pointer allocated by this.

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

matrix = calloc(size_x, sizeof(int*));

matrix = calloc(size_x,sizeof(int *));

The way you are doing it now,

你现在这样做的方式,

free(*first_matrix); free(first_matrix);

won't do what you want it to do.

不会做你想做的事。

#1


9  

Just because the memory has been free'd doesn't mean you can't access it! Of course, it's a very bad idea to access it after it's been free'd, but that's why it works in your example.

仅仅因为内存已经免费并不意味着你无法访问它!当然,在它被免费后访问它是一个非常糟糕的主意,但这就是为什么它适用于你的例子。

Note that free( *first_matrix ) only free's first_matrix[0], not the other arrays. You probably want some kind of marker to signify the last array (unless you will always know when you free the outer array how many inner arrays you allocated). Something like:

注意free(* first_matrix)只有free的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;
}

Then when you're freeing them:

然后当你释放它们时:

// keep looping until you find the NULL one
for( int i=0; first_matrix[i] != NULL; i++ ) {
    free( first_matrix[i] );
}
free( first_matrix );

#2


2  

You need to free each row individually:

您需要单独释放每一行:


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

#3


1  

Freeing the memory doesn't make it go away, it just means that another allocation might grab that same chunk of memory. Whatever you put in it will still be there until something else overwrites it.

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

Also, you're not freeing everything you allocated. You're only freeing the array of pointers and the first row. But even if you free everything correctly, you would still have the same effect.

此外,你没有释放你分配的一切。你只是释放了指针数组和第一行。但即使你正确地释放了一切,你仍然会有同样的效果。

If you want to create a "bus error" you need to point to memory that doesn't belong to your process. Why do you want to do that anyway?

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

#4


0  

You only freed the first row (or column) of first_matrix. Write another function like this:

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

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

You might want to make the matrix into a struct to store it's row and column count.

您可能希望将矩阵转换为结构以存储其行和列数。

#5


0  

I recommend using valgrind to track down unfree'd memory, as opposed to trying to make a bus error occur. It rocks for lots of other stuff as well.

我建议使用valgrind来追踪不*的内存,而不是试图发生总线错误。它还有许多其他东西。

Sam

#6


0  

You're getting memory leaks because you're freeing the first row of the matrix and the list of rows, but none of the 1 to nth rows. You need to call free in a loop.

您正在获得内存泄漏,因为您释放了矩阵的第一行和行列表,但没有释放第1行到第n行。你需要循环免费呼叫。

There are a couple of alternatives, however: - Allocate sizeof(int*)rows + rowscols*sizeof(int) bytes and use the first bytes for the row pointers. That way, you only have a single chunk of memory to free (and it's easier on the allocator, too) - Use a struct that contains the number of rows. Then you can avoid the row list altogether (saving memory). The only downside is that you have to use a function, a macro, or some messy notation to address the matrix.

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

If you go with the second option, you can use a struct like this in any C99 compiler, and again only have to allocate a single block of memory (of size numints*sizeof(int)+sizeof(int)):

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

struct matrix {
    int rows;
    int data[0];
}

#7


0  

The concept you are missing here, is that for every calloc, there must be a free. and that free must be applied to the pointer passed back from calloc.

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

I recommend you create a function (named delete_matrix) that uses a loop to free all of the pointers that you allocate in here

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

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

for(int i = 0; i ;>

then, once that is done, free the pointer allocated by this.

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

matrix = calloc(size_x, sizeof(int*));

matrix = calloc(size_x,sizeof(int *));

The way you are doing it now,

你现在这样做的方式,

free(*first_matrix); free(first_matrix);

won't do what you want it to do.

不会做你想做的事。