Domanda

Ho dei problemi con la produzione di una matrice int senza creare perdite di memoria. Voglio essere in grado di trasformare dinamicamente una data matrice (globale) in qualsiasi dimensione tramite read_matrix (). Ma poi voglio poter liberare la memoria in seguito. Quindi nel mio metodo principale il secondo printf dovrebbe comportare un errore del bus poiché non dovrebbe avere memoria assegnata ad esso. Come farei per creare questo?

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]);
}
È stato utile?

Soluzione

Solo perché la memoria è stata liberata non significa che non puoi accedervi! Certo, è una pessima idea accedervi dopo che è stato liberato, ma è per questo che funziona nel tuo esempio.

Nota che free( *first_matrix ) è solo gratuito first_matrix[0], non gli altri array. Probabilmente vuoi un qualche tipo di marker per indicare l'ultimo array (a meno che tu non sappia sempre quando liberi l'array esterno quanti array interni hai assegnato). Qualcosa del tipo:

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

Quindi quando li stai 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 );

Altri suggerimenti

Devi liberare ogni riga singolarmente:


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

Liberare la memoria non lo fa andare via, significa solo che un'altra allocazione potrebbe catturare lo stesso pezzo di memoria. Qualunque cosa tu inserisca sarà ancora lì fino a quando qualcos'altro lo sovrascriverà.

Inoltre, non stai liberando tutto ciò che hai assegnato. Stai solo liberando l'array di puntatori e la prima riga. Ma anche se liberassi tutto correttamente, avresti comunque lo stesso effetto.

Se si desidera creare un " errore bus " devi indicare una memoria che non appartiene al tuo processo. Perché vuoi farlo comunque?

Hai liberato solo la prima riga (o colonna) di first_matrix. Scrivi un'altra funzione come questa:

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

Potresti voler trasformare la matrice in una struttura per memorizzare il numero di righe e colonne.

Raccomando di usare valgrind per rintracciare la memoria non libera, invece di provare a fare un errore del bus. Oscilla anche per molte altre cose.

Sam

Stai riscontrando perdite di memoria perché stai liberando la prima riga della matrice e l'elenco delle righe, ma nessuna delle righe dall'1 all'ennesima. Devi chiamare gratuitamente in un ciclo.

Ci sono un paio di alternative, tuttavia: - Assegna sizeof (int *) righe + righe cols * sizeof (int) byte e usa i primi byte per i puntatori di riga. In questo modo, hai solo un singolo pezzo di memoria da liberare (ed è anche più facile sull'allocatore) - Utilizzare uno struct che contiene il numero di righe. Quindi è possibile evitare del tutto l'elenco delle righe (risparmiando memoria). L'unico aspetto negativo è che devi usare una funzione, una macro o qualche notazione disordinata per indirizzare la matrice.

Se vai con la seconda opzione, puoi usare una struttura come questa in qualsiasi compilatore C99, e di nuovo devi solo allocare un singolo blocco di memoria (di numeri di dimensioni * sizeof (int) + sizeof (int)):

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

Il concetto che ti manca qui, è che per ogni calloc, ci deve essere un libero. e che free deve essere applicato al puntatore passato da calloc.

Ti consiglio di creare una funzione (chiamata delete_matrix) che utilizza un ciclo per liberare tutti i puntatori qui allocati

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

quindi, una volta fatto, libera il puntatore assegnato da questo.

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

Il modo in cui lo stai facendo ora,

gratis (* first_matrix);     gratuito (first_matrix);

non farà ciò che vuoi che faccia.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top