简体   繁体   中英

Dynamic 2D array and memory free

I'm having a big troubles figuring out how to rightfully create a 2D dynamic array, how to assert the memory and how to free it in the end.

I'll show you parts of my code, and please tell me what I'm doing wrong.

I declare on the dynamic array in main function and send it to BuildMatrix function that is supposed to assert the needed memory to the array and fill it.

that's how I declared on the array and send it to the function Build:

int row, column, i, j;
int **matrix; 
BuildMatrix(&matrix, row, column);

now thats BuildMatrix decleration:

void BuildMatrix(int*** matrix, int row, int column);

And that's how I assert the memory (row and column have values that the user chose)

matrix =malloc(row * sizeof(int *));
for (i = 0; i < row; i++)
matrix[i] =malloc(column * sizeof(int));

Now so far everything works just fine, but when I try to free the memory, I get break point error

That's the function I used for freeing the memory:

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

The debugger show me that the error is on the first free (if I remove the first one, the second gives the error)

There is also another problem, but I think its to much for now, I'll ask later... :P

Thanks for your help!!

PS: If you got any good tutorials about pointers and dynamic arrays (I'd rather 2D+ arrays) I'd appreciate it a lot.

I do not think you need a *** pointer here, instead BuildMatrix could just return ** to main() . This design change would make your program easier, as working with *** can be a pain sometimes.

You also are not checking the return values of malloc() and scanf() , which can lead to future problems, and it's just safer to check those first. I also suggest you Don't cast result of malloc() , as this is not really needed in C.

With your errors of free() from the code you posted on @flintlock's answer, There is an inconsistency in your code:

You have declared:

void ExitAndFree(int** matrix, int row)

When this should be instead:

void ExitAndFree(int*** matrix, int row)

This change is needed in your code because you are calling &matrix in main for ExitAndFree() , so having **matrix in this function is not good enough. Again, this is because the code is using *** , which makes life harder.

Your code seems to work here with this change.

With these recommendations, you can also implement your program like this:

#include <stdio.h>
#include <stdlib.h>

int **BuildMatrix(int row, int column);
void PrintAndFree(int **matrix, int row, int column);

int main(void) {
    int **matrix, row, column;

    printf("\nPlease enter number of rows:\n");
    if (scanf("%d", &row) != 1) {
        printf("Invalid rows.\n");
        exit(EXIT_FAILURE);
    } 

    printf("\nPlease enter number of columns:\n");
    if (scanf("%d", &column) != 1) {
        printf("Invalid columns.\n");
        exit(EXIT_FAILURE);
    }

    matrix = BuildMatrix(row, column);

    PrintAndFree(matrix, row, column);

    return 0;
}

int **BuildMatrix(int row, int column) {
    int **matrix, rows, cols;

    matrix = malloc(row * sizeof(*matrix));
    if (matrix == NULL) {
        printf("Cannot allocate %d rows for matrix.\n", row);
        exit(EXIT_FAILURE);
    }

    for (rows = 0; rows < row; rows++) {
        matrix[rows] = malloc(column * sizeof(*(matrix[rows])));
        if (matrix[rows] == NULL) {
            printf("Cannot allocate %d columns for row.\n", column);
            exit(EXIT_FAILURE);
        }
    }

    printf("\nPlease enter values to the matrix:\n");
    for (rows = 0; rows < row; rows++) {
        for (cols = 0; cols < column; cols++) {
            if (scanf("%d", &matrix[rows][cols]) != 1) {
                printf("Invalid value entered.\n");
                exit(EXIT_FAILURE);
            }
        }
    }

    return matrix;
}

void PrintAndFree(int **matrix, int row, int column) {
    int rows, cols;

    printf("\nYour matrix:\n");
    for (rows = 0; rows < row; rows++) {
        for (cols = 0; cols < column; cols++) {
             printf("%d ", matrix[rows][cols]);
        }
        free(matrix[rows]);
        matrix[rows] = NULL;
        printf("\n");
    }

    free(matrix);
    matrix = NULL;
}

Here a copy&paste ready example...

#include <stdlib.h>

void BuildMatrix(int*** matrix, int row, int column) {
    *matrix = malloc(row * sizeof(int *));
    int i;
    for (i = 0; i < row; i++)
        (*matrix)[i] = malloc(column * sizeof(int));
}

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

int main()
{
    int row = 10, column = 10;
    int **matrix;
    BuildMatrix(&matrix, row, column);
    ExitAndFree(matrix, row);

    return 0;
}

However I would strongly recommend against working with raw pointers and separate variables for matrix directly. A better solution Software Engineering wise would be to either use an existing matrix library, or writer your own matrix library in C with struct...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM