I have a matrix dinamically allocated of char or something else like this:
char **ptr;
ptr = (char**)malloc(sizeof(char*) * 3);
*ptr = (char*)malloc(4);
*(ptr + 1) = (char*)malloc(4);
*(ptr + 2) = 0;
If I will free the lines of matrix without free the memory of pointers like
int i;
for(i = 0; i < 2; i++)
free(*(ptr + i));
will be free all lines beside the last one before the null pointer, in this case will be free only the *ptr line. To free and the last one we need to add one more instruction
free(ptr);
The question is what it works like this and why we can't to free only the pointers memory or only the string memory of that matrix?
I believe there are two issues with the way you may be thinking of memory allocation.
Firstly, you appear to be thinking of the matrix as being allocated inside the memory as a visual matrix. But you must remember that the compiler does not have a concept of a matrix. It also does not know that the memory you allocate as a starting point, in a row of a matrix, points to the row.
Secondly, you must explicitly tell the compiler what you want to happen, rather than relying on the compiler to guess, which may also cause undefined behaviour.
I'll use 8-bit addresses to illustrate this.
Take ptr = (char**)malloc(sizeof(char*) * 3)
, it may allocate addresses at 0x30 0x31 0x32
, which will store an 8-bit type each. Suppose that you do *(ptr + 0) = malloc(4)
. The malloc call will return a pointer to four consecutive locations where chars can be stored. Suppose it returns 0x40
this means that addresses 0x40 0x41 0x42 0x43
are all available to use.
However, the value at address 0x30 is assigned 0x40, now remember that a pointer is not a type, but rather a binary representation of a number, that happens to represent an address. Therefore, pointers do not have the luxury of a deallocator (e.g. a destructor in C++). The compiler does not know that this value is used to access an allocated address of memory but rather stores that value for you. Calling free(ptr)
will only free the addresses 0x30 0x31 0x32
for this reason.
Simply put, suppose you have four integers stored in an int*
as 1 2 3 4
, if the compiler attempted to free the four integers as addresses, you will run into issues as you are literally telling the compiler to free
addresses 0x01 0x02 0x03 0x4
which on an old system would have dire consequences, and on modern systems, you're application would be terminated.
This may seem inconvenient initially, however, this implies some flexibility in using these pointers. For example, you may wish to use ptr
again, instead of making a call to free
and another call to malloc
, to point at another matrix.
If freeing all rows of a matrix also freed the pointers to the rows, you may have a situation where you run into segmentation faults because you were unaware of a pointer pointing to this address.
In saying this, it is your responsibility to keep track of this and make sure that the heap does not accumulate data that has no references pointing to it.