Pregunta

Tengo algunos problemas para producir una matriz int sin crear pérdidas de memoria.Quiero poder convertir una matriz determinada (global) en cualquier tamaño de forma dinámica a través de read_matrix().Pero luego quiero poder liberar la memoria más adelante.Entonces, en mi método principal, el segundo printf debería generar un error de bus ya que no debería tener memoria asignada.¿Cómo haría para crear esto?

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]);
}
¿Fue útil?

Solución

¡El hecho de que la memoria haya sido liberada no significa que no puedas acceder a ella!Por supuesto, es un muy mal Es idea acceder a él después de haberlo liberado, pero es por eso que funciona en su ejemplo.

Tenga en cuenta que free( *first_matrix ) solo gratis first_matrix[0], no las otras matrices.Probablemente desee algún tipo de marcador para indicar la última matriz (a menos que siempre sepa cuando libere la matriz externa cuántas matrices internas asignó).Algo como:

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;
}

Luego, cuando los estés liberando:

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

Otros consejos

Debes liberar cada fila individualmente:


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

Liberar la memoria no hace que desaparezca, sólo significa que otra asignación podría apoderarse de esa misma porción de memoria.Todo lo que pongas seguirá ahí hasta que algo más lo sobrescriba.

Además, no estás liberando todo lo que asignaste.Solo estás liberando la matriz de punteros y la primera fila.Pero incluso si liberas todo correctamente, seguirás teniendo el mismo efecto.

Si desea crear un "error de bus", debe apuntar a una memoria que no pertenece a su proceso.¿Por qué quieres hacer eso de todos modos?

Solo liberaste la primera fila (o columna) de first_matrix.Escribe otra función como esta:

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

Es posible que desee convertir la matriz en una estructura para almacenar su recuento de filas y columnas.

Recomiendo usar valgrind para rastrear la memoria no liberada, en lugar de intentar provocar un error en el bus.También es excelente para muchas otras cosas.

Sam

Estás teniendo pérdidas de memoria porque estás liberando la primera fila de la matriz y la lista de filas, pero ninguna de las filas 1 a n.Necesitas llamar gratis en bucle.

Sin embargo, existen un par de alternativas:- Asignar tamaño de (int*)filas + filascols*sizeof(int) bytes y utilice los primeros bytes para los punteros de fila.De esa manera, solo tiene una sola parte de la memoria para liberar (y también es más fácil para el asignador): use una estructura que contenga el número de filas.Entonces puedes evitar la lista de filas por completo (ahorrando memoria).El único inconveniente es que tienes que usar una función, una macro o alguna notación desordenada para abordar la matriz.

Si opta por la segunda opción, puede usar una estructura como esta en cualquier compilador C99 y nuevamente solo tendrá que asignar un único bloque de memoria (de tamaño numints*sizeof(int)+sizeof(int)):

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

El concepto que te falta aquí es que para cada calloc, debe haber un free.y ese free debe aplicarse al puntero devuelto desde calloc.

Le recomiendo que cree una función (llamada Delete_Matrix) que usa un bucle para liberar todos los punteros que asignas aquí.

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

luego, una vez hecho esto, libere el puntero asignado por esto.

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

La forma en que lo estás haciendo ahora,

gratis(*first_matrix);gratis (primera_matriz);

no hará lo que quieres que haga.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top