Hi,
In my text book the de-allocation of a dynamically allocated matrix is carried out thus:
Why is it mandatory to include free(mat[0]) and free(mat) is not enough?Code:void freeMatrix(char** mat) { free(mat[0]); free(mat); }
Hi,
In my text book the de-allocation of a dynamically allocated matrix is carried out thus:
Why is it mandatory to include free(mat[0]) and free(mat) is not enough?Code:void freeMatrix(char** mat) { free(mat[0]); free(mat); }
Look in your textbook for the allocation of the matrix, and observe how that matches the de-allocation.
Look up a C++ Reference and learn How To Ask Questions The Smart WayOriginally Posted by Bjarne Stroustrup (2000-10-14)
After doing what Laserlight said and you are sure you understood, you can take a look at this example too.
Code - functions and small libraries I use
It’s 2014 and I still use printf() for debugging.
"Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson
Depending on how the matrix is allocated, even including free(mat[0]) may not be enough. If each row (or column if allocating in column major order) is a separate call to malloc, then those calls must all be mirrored when freeing:
Without knowing how the matrix is allocated, it is difficult to say whether the freeMatrix function in your textbook is correct or not. Erring on the side of trust, I would say it is correct and that the matrix is allocated like so:Code:void free_matrix(char **matrix, size_t rows) { size_t i; for (i = 0; i < rows; i++) { free(matrix[i]); } free(matrix); }
Notice that the number of calls to free perfectly match the number of calls to malloc.Code:#include <stdio.h> #include <stdlib.h> #define ROWS 10 #define COLS 10 int main(void) { int **matrix = (int**)malloc(ROWS * sizeof *matrix); int *mem = (int*)malloc(COLS * ROWS * sizeof *mem); size_t i, j; /* Link blocks from mem to matrix */ for (i = 0; i < ROWS; i++) { matrix[i] = mem + (i * COLS); } /* Use matrix just like an array */ for (i = 0; i < ROWS; i++) { for (j = 0; j < COLS; j++) { matrix[i][j] = (int)(j * i + 1); } } for (i = 0; i < ROWS; i++) { for (j = 0; j < COLS; j++) { printf("%3d", matrix[i][j]); } puts(""); } /* Correctly free all memory */ free(matrix[0]); /* free(mem) works too */ free(matrix); return EXIT_SUCCESS; }
You surely did not check the example I provided above!
You need also to read about casting malloc.
Code - functions and small libraries I use
It’s 2014 and I still use printf() for debugging.
"Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson
Hence my suggestion to look at how the matrix is allocatedOriginally Posted by sonjared
Look up a C++ Reference and learn How To Ask Questions The Smart WayOriginally Posted by Bjarne Stroustrup (2000-10-14)
Nor do I care. Duplicated effort does not equate to wasted effort. Often different perspectives on and descriptions of the same topic help to clarify the concept.
I'm aware of the issues. Just be cause my choices are different from yours does not make them incorrect.
Lol the quote of the year, Imo : "I'm aware of the issues. Just because my choices are different from yours does not make them incorrect."
Obviously what sonjared said does not worth a comment (but because everyone deserves a second chance, let me inform you that the link comes from the faq ).
As for the question, I came into a situation where I needed to write the exact same free function.
So check the link here, I have draw a picture too, so that one can see why we need to free like this.
Code - functions and small libraries I use
It’s 2014 and I still use printf() for debugging.
"Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson
How kind of you to give me a second chance at continuing to be correct. Allow me to quote from the FAQ you hold in such high esteem:
Please note that I did not fail to include stdlib.h. This point is moot, and I was aware of that particular "problem" with casting malloc before reading your FAQ.There is nothing wrong with this except in the event that stdlib.h, the header which declares malloc, is not included.
I have been writing code for a long time, and cannot remember encountering a single instance of this situation that was not caught by the compiler, much less lint. If one is making code changes like that without looking at warnings or de-linting the result, one gets what one deserves.Also, during maintenance, if the type of the pointer changes but the cast is not changed, once again there is a difficult to find bug.
I notice that the FAQ fails to mention C++ compatibility, which is a primary reason why I cast the result of malloc. But I also notice the trailing comment, which you seem to have neglected when trying to chastise me about my perfectly valid choice:
Is what I say worth a comment now?However, you should use whichever you like provided you are aware of the issues.
O_oIs what I say worth a comment now?
No.
o_O
Wait...
NOOOOOOooooo!
Soma
> Please note that I did not fail to include stdlib.h. This point is moot, and I was aware of that particular "problem" with
> casting malloc before reading your FAQ.
The problem with the cast isn't when you include stdlib.h, it's when you FAIL to include stdlib.h and you've cast the result of malloc. In this case, the error (in the mis-declaration of malloc) is masked by the cast. C99 is better in this respect, since it removed the "implicit declaration rule", so not including stdlib.h in C99 is no longer an option.
> I notice that the FAQ fails to mention C++ compatibility, which is a primary reason why I cast the result of malloc.
If a cast of malloc were the only difference between C and C++, you might have a point.
However, there are a whole host of differences which make most non-trivial C programs more challenging to work the same in C++ (for example all those extra C++ keywords which are valid identifiers in C - int class; anyone).
Incompatibilities Between ISO C and ISO C++
If you really want a C++ program, then use std::vector, or failing that, the new operator.
Using malloc in a C++ program, on something which is a class / struct (with a constructor) is just woe compounding woe.
You should look up Polyglots sometime. Programs valid in multiple languages are seldom good examples of programming style in any language.
> and cannot remember encountering a single instance of this situation that was not caught by the compiler, much less lint
You are fortunate enough to have a decent set of tools.
However, half the people who roll into this forum (and pretty much every other forum) are still using fossil TurboC.
If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
If at first you don't succeed, try writing your phone number on the exam paper.
I don't fail to include stdlib.h, so it's not my problem. If I were ever to post code that does so, you're welcome to bash me and then gloat about it, but that won't happen.The problem with the cast isn't when you include stdlib.h, it's when you FAIL to include stdlib.h and you've cast the result of malloc. In this case, the error (in the mis-declaration of malloc) is masked by the cast. C99 is better in this respect, since it removed the "implicit declaration rule", so not including stdlib.h in C99 is no longer an option.
Casting malloc is one of many things I do to maintain compatibility. It appears that I mistakenly assumed this would be obvious.If a cast of malloc were the only difference between C and C++, you might have a point.
Thus completely missing the point. Rest assured, when I want C++ and just C++, I do write C++.If you really want a C++ program, then use std::vector, or failing that, the new operator.
Once again, not my problem.However, half the people who roll into this forum (and pretty much every other forum) are still using fossil TurboC.
O_oOnce again, not my problem.
Well, yeah, it is your problem; you've kind of made it a point to make it your problem by saying the problem is questionable or even imaginary.
So, you have limited experience in that you've only had decent tools, but you are using that limited view to forward casting the return value from `malloc' over not casting the return value.I have been writing code for a long time, and cannot remember encountering a single instance of this situation that was not caught by the compiler, much less lint.
Just because you've never seen tools that misses an improper cast from `malloc' doesn't mean that such don't exist and aren't unfortunately prolific.
Soma
> Once again, not my problem.
Even for a programmer, you're remarkably self-centred.
This isn't about you and your wonderful set of tools, it's about informing newbies the best way(s) of getting the best results across a whole variety of tools. Outside of your perfect little world, casting malloc in C causes more harm than good.
If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
If at first you don't succeed, try writing your phone number on the exam paper.