2

Here's my code:

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

#define M 5
#define N 3

double **create_matrix(int m, int n);
void    destroy_matrix(double **matrix, int m);

int main(void)
{
  int i = 0, j = 0;
  int x = 0;
  double **matrix;

  matrix = create_matrix(M, N);

  while (i < M) {
    j = 0;
    while (j < N) {
      printf("%4.0f", *(*(matrix + j) + i) = j);
      j++;
    }
    putchar('\n');
    i++;
  }

  destroy_matrix(matrix, M);

  return 0;
}

double **create_matrix(int m, int n)
{
  int i = 0;
  double **matrix;

  if ((matrix = (double **) malloc(sizeof(double *) * m)) != NULL) {
    while (i < m)
      if ((*(matrix + i++) = (double *) malloc(sizeof(double) * n)) == NULL)
        return NULL;

    return matrix;
  } else
    return NULL;
}

void destroy_matrix(double **matrix, int m)
{
  int i = 0;

  while (i < m)
    free((void *) *(matrix + i++));

  free((void *) matrix);
}
  • Allocating, initializing and printing the matrix works.
  • Allocating, not initializing and freeing works.
  • Allocating, initializing AND freeing does NOT work.

Backtrace:

*** glibc detected *** [file]: free(): invalid next size (fast): 0x0000000001e7d040 ***

Followed by a memory map.

I searched for similar problems but couldn't find one fitting my situation, nor could I derive mine from them.

unwind
  • 391,730
  • 64
  • 469
  • 606
enlightened
  • 59
  • 2
  • 9
  • By the way, http://stackoverflow.com/questions/1733881/c-correctly-freeing-memory-of-a-multi-dimensional-array is exactly the same problem, although considering you tested and thought freeing was working, I can understand the confusion. At the very least, that link has some code that you may find helpful – sirlark Jan 17 '12 at 11:44
  • Not _exactly_ though ... without the initialization, which, as it turned out, was the problem. – enlightened Jan 17 '12 at 11:50

2 Answers2

1

Your matrix allocation and deallocation functions look fine to me. But the initialization of the matrix elements has an error:

  while (i < M) {
    j = 0;
    while (j < N) {
      printf("%4.0f", *(*(matrix + j) + i) = j);
      j++;
    }
    putchar('\n');
    i++;
  }

This expression

*(*(matrix + j) + i)

has to be changed by this expression

*(*(matrix + i) + j)

because i are your rows and j are your columns.

Note that you could also use the simpler form matrix[i][j] which is equivalent to *(*(matrix + i) + j) in your program.

ouah
  • 142,963
  • 15
  • 272
  • 331
0

You are freeing the dereference, i.e. the address pointed to by the contents of the array. Try this instead. Note the lack of '*' before '(matrix + i++) on line 6

void destroy_matrix(double **matrix, int m)
{
  int i = 0;

  while (i < m)
    free((void *) (matrix + i++));

  free((void *) matrix);
}
sirlark
  • 2,187
  • 2
  • 18
  • 28
  • But if `matrix` is a pointer to an array of pointers, then surely there must be at least one dereference for each row? – unwind Jan 17 '12 at 11:37
  • pointer are integers, your `+ i++` is the same as saying matrix[i] which is a dereference already – sirlark Jan 17 '12 at 11:38
  • come to think of it, I can't remember whether the type size is taken into account doing pointer arithmetic this way... you might even need to explicitly multiply i by sizeof(double*) – sirlark Jan 17 '12 at 11:39
  • Dereferencing once is needed, I think. Without, it gives me: `free(): invalid pointer`. I'm going to try explicit multiplication now ... – enlightened Jan 17 '12 at 11:43
  • so I just wrote a quick test program, and pointer arithmetic does the sensible thing, i.e. +1 adds sizeof(pointer type), regardless or the operator used (addition, preincrement, postincrement). So sorry, pointers are not integers in the strict sense of the integer type. They are however integers, and if you're doing pointer arithmetic like you are, can be thought of as integers (in the mathematical sense) – sirlark Jan 17 '12 at 12:00
  • Also, I don't understand why the free works with the additional dereference. Isn't `free((void *) *(matrix + i++))` the same as `free((void *) *matrix[i])`? – sirlark Jan 17 '12 at 12:02
  • No: `*(matrix + i)` is equivalent to `matrix[i]`, the latter form being only syntactic sugar. Without the dereference you'd be trying to free the memory 'from within it' (because `matrix` == `matrix + 0` == the beginnging of the allocated memory) instead of through pointing at the beginning of it. The point of the `while` here is to free the second 'dimension' of the matrix, which consists of chunks of memory used for the columns at which `matrix[0...n]` point. Hope I hit the right answer ... and question. – enlightened Jan 17 '12 at 14:10