cgnx
cgnx

Reputation: 113

Returning NULL pointer

I have function that deallocates struct:

typedef struct matrix_t {
  int r; // num of rows
  int c; // num of cols
  int *values;
} matrix_t;

function that does that is:

void deallocate_matrix(matrix_t **ptr) {
  if (ptr != NULL && *ptr != NULL) {
    free((*ptr)->values);
    (*ptr)->values = NULL;
    free(*ptr);
    *ptr = NULL;
  }
}

Then my main:

int main(int argc, char *argv[]) {
  matrix_t *M[4] = {NULL};
  char op[2] = {0};
  int op_ret[2] = {0};
  M[0] = matrix_input();
  scanf(" %c", &op[0]);
  M[1] = matrix_input();
  M[2] = calc(M[0], M[1],op[0]);
  matrix_print(M[2]);
  deallocate_matrix((matrix_t **)&M[1]);
  assert(M[1] == NULL); //this looks ok, M[1] is NULL
  return 0;
}

But if I omit deallocate_matrix((matrix_t **)&M[1]); and deallocate with function calc like this:

matrix_t *calc(matrix_t *A, matrix_t *B, char op) {
  matrix_t *M = NULL;
  //some code to compute M
  deallocate_matrix((matrix_t **)&A);
  deallocate_matrix((matrix_t **)&B);
  return M;
}

the assertion M[1]==NULL would fail, so I am clearly doing something wrong in the calc function, but I am not sure what.

Upvotes: 0

Views: 85

Answers (1)

David Schwartz
David Schwartz

Reputation: 182753

Your code is correct. The assert is wrong. Get rid of it and you won't have an issue. You have freed the matrix.

What's happening is that calc takes A and B by value. So it can't change the value of A or B in the caller. So they won't be NULL after the call.

  M[2] = calc(M[0], M[1],op[0]);

Here, we pass the values of M[0] and M[1] to calc. So calc can't change the value of M[0] or M[1] because it doesn't get a pointer to them. That's fine. There no reason it should.

Please just get out of the habit of senselessly setting pointers to NULL when you deallocate what they point to. It causes lots of pain the more complex your code gets.

You see the way free works, right? Your functions should work the same way for sanity, so:

void deallocate_matrix(matrix_t *ptr) {
  if (ptr != NULL) {
    free(ptr->values);
    free(ptr);
  }
}

Simple and easy to use.

Upvotes: 1

Related Questions