-1

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!!

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

eddie
  • 1,252
  • 3
  • 15
  • 20
  • So, where is the 2D array? There is none in the code shown. `int **` is no 2D array and cannot point to one. Being a 3-star C programmer is not a compliment. `***` is typically a signal for wrong interface design. – too honest for this site Jan 12 '17 at 03:09
  • Replace `matrix` with `*matrix`, or use a temporary variable `int **temp = *matrix` to make things slightly less mind bending. (You'll need a `*matrix = temp` at the end if using the temporary variable.) – user3386109 Jan 12 '17 at 03:09
  • @Olaf in the task I got, the function Build is declared as I posted, with 3 stars (***) – Matan Benishty Jan 12 '17 at 03:22
  • @user3386109 still doesnt work :X I get acces violation error now – Matan Benishty Jan 12 '17 at 03:23
  • That sheds a bad light on the original author and the quality of your course. Worse, if they indeed call that construct 2D array (dynamic or not does not make a difference). You should read a good (and modern, at least for C99, better the current version C11) C book. Your teacher seems to be stuck with C constructs which are obsolate since 18 years now (and was actually the worse of two possible workarounds back then). Feel free to cite me in class: Learn about VLAs. – too honest for this site Jan 12 '17 at 03:34
  • I haven't said a word about my lecturer and you already figured it out... Yup my lecturer is really bad... Im learning everything on my own (and thats why Im so lake in knowledge..) – Matan Benishty Jan 12 '17 at 03:40
  • @MatanBenishty Why are you using `***`? Surely `**` for your matrix is fine. – RoadRunner Jan 12 '17 at 04:38
  • @RoadRunner thats part of the task, thats what they want it to be for some reason – Matan Benishty Jan 12 '17 at 07:08
  • @MatanBenishty I guess that is fine. As others have said, your lecturer is not doing a good job if he wants you to use `***`. With that said, I guess you will be very good with pointers if you can use `***` pointers, I just think it is so unnecessary for what your trying to do. – RoadRunner Jan 12 '17 at 07:12
  • @RoadRunner Yeah... Especially when you are new to that.. Ive been trying to work on that for so long... I've reached another problem I cant figure out by myself whats wrong... When I enter same number of rows and columns it works smooth, but when they are not equal, I get error when I send "temp" array to free function . BTW, do I actually need to free the array if its local array? – Matan Benishty Jan 12 '17 at 07:28
  • @MatanBenishty Basically anything you allocate with `malloc()`, you need to `free()` it. – RoadRunner Jan 12 '17 at 08:04
  • @RoadRunner sigh... Well then I have 2 problems. The first one is when I enter to column higher number then row. It cause a writting location error.. ---------And the second is if I try to free the memory of the temp array, it gives me an error in the line" free(matrix);" – Matan Benishty Jan 12 '17 at 08:09
  • @MatanBenishty: So why not pick a good C book and ignore your lecturer? There is a list somewhere on SO. Find it. – too honest for this site Jan 12 '17 at 13:31

2 Answers2

1

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;
}
Community
  • 1
  • 1
RoadRunner
  • 25,803
  • 6
  • 42
  • 75
  • Oh wow I see, I'll add that. BTW, whats the difference between exit(1) to exit(EXIT_FAILURE)? Because we are doing it with exit(1) – Matan Benishty Jan 12 '17 at 07:00
  • They are very similar. `exit(1)` is for unsuccessful termination. `EXIT_FAILURE` just another way of doing the same thing. Just stick with `exit(1)`, it doesn't really matter much which one you use. – RoadRunner Jan 12 '17 at 07:08
  • Thank you so much for everything man! I've learned a lot! ---------------- Could you please take a look in my last reply to flintlock answer? I've reached another problem -_-' – Matan Benishty Jan 12 '17 at 07:11
  • @MatanBenishty, I have been looking at your code on codeshare, but I am a little confused as to what your trying to do with `void Transpose()`. – RoadRunner Jan 12 '17 at 08:06
  • it need to transpose the matrix, if its 3x2, it will change it to 2x3 – Matan Benishty Jan 12 '17 at 08:10
  • do you want to talk on facebook maybe? ill explain you everything – Matan Benishty Jan 12 '17 at 08:43
0

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...

user3386109
  • 34,287
  • 7
  • 49
  • 68
flintlock
  • 97
  • 7
  • I know! But right now in the task Im not allowed to use these libraries. Thanks a lot, Ill try that and see if it solve my problem – Matan Benishty Jan 12 '17 at 03:26
  • There is a problem in entering values to the array. At matrix[1][0] im getting acces violation writing error – Matan Benishty Jan 12 '17 at 03:34
  • Could you show me your code? I ran valgrind with some array access and didn't get any error. – flintlock Jan 12 '17 at 03:45
  • line 33: scanf("%d", &matrix[i][j]); // TODO: <-- should be &((*matrix)[i][j]) – flintlock Jan 12 '17 at 05:06
  • EDIT: Ok I found out what was wrong!! Thank you so much, its working!! ----------------- But anyway, if you have a good tutorial with some more advanced examples of how to use 2D dynamic arrays and pointers, I'd appreciate that. – Matan Benishty Jan 12 '17 at 05:38
  • run `valgrind ./filename.exe -v` – flintlock Jan 12 '17 at 05:43
  • Hey, could you please take a look in my code again? When I try to free the temp array in the function Transpose (line 86), there is an error. --------------I found out that whenever row != column, I get that error, when they are even it works fine without any errors – Matan Benishty Jan 12 '17 at 07:04