Frage

Ich habe einige Probleme mit der Erzeugung einer Int -Matrix, ohne Speicherlecks zu erstellen. Ich möchte in der Lage sein, eine bestimmte (globale) Matrix über read_matrix () dynamisch in jede Größe zu machen. Aber dann möchte ich später in der Lage sein, den Speicher zu befreien. In meiner Hauptmethode sollte der zweite Printf zu einem Busfehler führen, da es keinen Speicher haben sollte. Wie würde ich das erstellen?

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]);
}
War es hilfreich?

Lösung

Nur weil der Speicher frei war, heißt das nicht, dass Sie nicht darauf zugreifen können! Natürlich ist es ein sehr schlecht Die Idee, darauf zuzugreifen, nachdem es frei war, aber deshalb funktioniert es in Ihrem Beispiel.

Beachten Sie, dass free( *first_matrix ) Nur frei first_matrix[0], nicht die anderen Arrays. Sie möchten wahrscheinlich, dass eine Art Marker das letzte Array bedeutet (es sei denn, Sie werden immer wissen, wann Sie das äußere Array befreien, wie viele innere Arrays Sie zugewiesen haben). Etwas wie:

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

Dann, wenn Sie sie befreien:

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

Andere Tipps

Sie müssen jede Zeile einzeln befreien:


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

Wenn Sie das Gedächtnis befreien, verschwinden sie nicht, sondern nur, dass eine andere Zuweisung denselben Speicherbeteiliger erfasst. Was auch immer Sie hineingeben, wird immer noch da sein, bis etwas anderes es überschreibt.

Außerdem befreien Sie nicht alles, was Sie zugewiesen haben. Sie befreien nur die Reihe von Zeigern und die erste Reihe. Aber selbst wenn Sie alles richtig befreien, hätten Sie immer noch den gleichen Effekt.

Wenn Sie einen "Busfehler" erstellen möchten, müssen Sie auf den Speicher hinweisen, der nicht zu Ihrem Prozess gehört. Warum willst du das überhaupt tun?

Sie haben nur die erste Zeile (oder Spalte) von First_Matrix befreit. Schreiben Sie eine andere Funktion wie diese:

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

Möglicherweise möchten Sie die Matrix zu einer Struktur machen, um die Zeile und die Spaltenzählung zu speichern.

Ich empfehle, Valgrind zu verwenden, um den ungefressenen Speicher aufzuspüren, anstatt zu versuchen, einen Busfehler aufzutreten. Es rockt auch für viele andere Sachen.

Sam

Sie erhalten Speicherlecks, weil Sie die erste Zeile der Matrix und die Liste der Zeilen befreien, aber keine der 1 bis zu N -ten Zeilen. Sie müssen in einer Schleife frei anrufen.

Es gibt jedoch einige Alternativen: - Zuordnen der Größe (int*)Zeilen + Zeilencols*sizeof (int) Bytes und verwenden Sie die ersten Bytes für die Zeilenzeiger. Auf diese Weise haben Sie nur einen einzigen Speicherbetrag zum freien Raum (und es ist auch für den Allocator einfacher) - verwenden Sie eine Struktur, die die Anzahl der Zeilen enthält. Dann können Sie die Zeilenliste insgesamt vermeiden (Speicherspeicher). Der einzige Nachteil ist, dass Sie eine Funktion, ein Makro oder eine unordentliche Notation verwenden müssen, um die Matrix anzusprechen.

Wenn Sie sich mit der zweiten Option befassen, können Sie eine solche Struktur in jedem C99 -Compiler verwenden und müssen erneut einen einzelnen Speicherblock (von Größenzahlen*sizeof (int)+sizeof (int)) zuweisen:

struct matrix {
    int rows;
    int data[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.

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

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

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

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.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top