20

I created a 2-D matrix using double pointer like that:

int** pt; pt = (int*) malloc(sizeof(int)*10);

I know that a pointer is freed like that

free(ptr);

How can we free the double pointer?

What if we print something and later freed that memory and exit the program? Does the final memory consist of that which we used or it will be same as initial?

Eitan T
  • 32,660
  • 14
  • 72
  • 109
bledi
  • 301
  • 3
  • 6
  • 14
  • 3
    That depends on how you called `malloc`. Where's the code? – Eitan T Jun 13 '12 at 13:00
  • @bledi So you need to iterate through these pointers, and free the pointed data first. Then free the pointers themselves. Look at Attila's answer. – Eitan T Jun 13 '12 at 13:05
  • Ditto on putting up the relevant malloc code. – octopusgrabbus Jun 13 '12 at 13:06
  • In C, do not cast the result of a call to `malloc()`, `realloc()`, or `calloc()` - it is unnecessary and potentially hides the serious error of a missing prototype. – mlp Jul 15 '19 at 15:57

3 Answers3

41

Say you have a matrix mat

int** mat = malloc(10 * sizeof(int*));
for (int i=0; i<10; ++i) {
  mat[i] = malloc(10 * sizeof(int));
}

then you can free each row of the matrix (assuming you have initialized each correctly beforehand):

for (int i=0; i<10; ++i) {
  free(mat[i]);
}

then free the top-level pointer:

free(mat);

For your second question: if you allocate memory and use it, you will change that memory, which will not be "reverted" even if you free it (although you will not be able to access it reliably/portably any more).

Note: the top-level malloc is using sizeof(int*) as you are allocating pointer-to-ints, not ints -- the size of int* and int are not guaranteed to be the same.

Alexander Ciesielski
  • 10,506
  • 5
  • 45
  • 66
Attila
  • 28,265
  • 3
  • 46
  • 55
2

If your matrix isn't "ragged", i.e. all rows have the same length, you might want to consider:

  1. Accessing it manually, i.e. just treat it as a 1D array of values, and keep a separate width value. To access an element at (x,y) use mat[y * width + x].
  2. If you really want the convenience of mat[y][x], you can improve it by doing a single call to malloc() that allocates both the pointer array and all the rows, then initializing the pointers to point at each row. This has the advantage that it can all be free:ed with a single free(mat); call.

The second approach would look something like this:

double ** matrix_new(size_t width, size_t height)
{
  double **p = malloc(height * sizeof *p + width * height * sizeof **p);
  double *e1 = (double *) (p + height);
  size_t i;

  for(i = 0; i < height; ++i)
    p[i] = e1 + i * width;
  return p;
}

Note: the above is un-tested, and production code should obviously check for failure before using p.

unwind
  • 391,730
  • 64
  • 469
  • 606
  • 2
    if you free just the top level pointer, the buffers pointed by the internal level are not referenced, are they freed by default by some garbage collector ????. or they should be explicitly freed??? –  Sep 03 '14 at 17:50
  • 1
    Unless I'm misunderstanding this, you're allocating space for both an array `double *`, and a 2d array of `double` of size `width * height`. Why isn't it `malloc(height * sizeof(double *) + width * height * sizeof(double)`? The `+ width * height` part of your malloc would only allocate one byte per `double` in the matrix, which is not enough space. – Michael Dorst Oct 13 '19 at 20:04
  • @MichaelDorst Because it was a bug, now fixed. Many thanks. – unwind Oct 14 '19 at 14:01
  • But you didnt put the `free()` sentence; @MichaelDorst are you reffering to this? `len = sizeof(int *) * rows + sizeof(int) * columns * rows;` and `arr = (int **)malloc(len);`. In this case l wanted to know how to liberate this double pointer tho. – vincent thorpe Feb 01 '20 at 15:29
  • @vincentthorpe I don't know what you're asking. – Michael Dorst Feb 01 '20 at 17:14
2

For the first question, I'll tell you the rule of thumb.

The number of times you call free() should be equal to the number of times you call malloc() + the number of times you call calloc().

So if you allocated in such a way that you made a pointer to pointers to ints, and then used malloc() on each pointer to ints, then you'll free "row" number of times, where each free() is for each pointer to ints.

And a final free() is called on the pointer to pointers to ints. That will balance out the malloc() + calloc() with free() calls.

Anton Menshov
  • 2,266
  • 14
  • 34
  • 55
Thorfinn
  • 43
  • 5
  • "The number of times you call free() should be equal to the number of times you call *alloc()", that summarizes it. I would like to clarify another thing though, according to https://en.cppreference.com/w/c/memory/free we need to pass a single pointer to free, then what happens when we pass a double pointer? Implicit cast to single pointer? – KcFnMi Feb 18 '23 at 15:50