2

I am relatively new to C and have coded (or more precise: copied from here and adapted) the functions below. The first one takes a numpy array and converts it to a C int array:

int **pymatrix_to_CarrayptrsInt(PyArrayObject *arrayin) {
   int **result, *array, *tmpResult;
   int i, n, m, j;

   n = arrayin->dimensions[0];
   m = arrayin->dimensions[1];
   result = ptrvectorInt(n, m);

   array = (int *) arrayin->data; /* pointer to arrayin data as int */
   for (i = 0; i < n; i++) {
      result[i] = &array[i * m];
   }
   return result;
}

The second one is used within the first one to allocate the necessary memory of the row vectors:

int **ptrvectorInt(long dim1, long dim2) {
   int **result, i;
   result = malloc(dim1 * sizeof(int*));
   for (i = 0; i < dim1; i++) {
     if (!(result[i] = malloc(dim2 * sizeof(int)))){
        printf("In **ptrvectorInt. Allocation of memory for int array failed.");
        exit(0);
     }
   }
   return result;
}

Up to this point everything works quite fine. Now I want to free the memory occupied by the C array. I have found multiple threads about how to do it, e.g. Allocate and free 2D array in C using void, C: Correctly freeing memory of a multi-dimensional array, or how to free c 2d array. Inspired by the respective answers I wrote my freeing function:

void free_CarrayptrsInt(int **ptr, int i) {

    for (i -= 1; i >= 0; i--) {
        free(ptr[i]);
    }
    free(ptr);
}

Nontheless, I found out that already the first call of free fails - no matter whether I let the for loop go down or up.

I looked for explenations for failing free commands: Can a call to free() in C ever fail? and free up on malloc fails. This suggests, that there may have been a problem already at the memory allocation. However, my program works completely as expected - except memory freeing. Printing the regarded array shows that everything should be fine. What could be the issue? And even more important: How can I properly free the array?

I work on a Win8 64 bit machine with Visual Studio 10 64bit compiler. I use C together with python 3.4 64bit.

Thanks for all help!

Community
  • 1
  • 1
Samufi
  • 2,465
  • 3
  • 19
  • 43
  • I think @user3121023 is right; not only does this assignment cause a memory leak since you lose the pointers to the allocated memory, you also try to call `free` on the pointers stored in `result`, but they're not pointing to the memory _you_ have allocated, since you took them from `arrayin->data`. – user4520 May 27 '15 at 20:30
  • Thanks for your comments user3121023 and @szczurcio. I guess I did not understand everything correctly but finally figured out a solution that works. I would be glad if you could look over my comment to the answer of user3121023 to make sure I understood everything well. I am a little bit worried that my solution only works because of good luck and will cause a memory leak later or on other machines... – Samufi May 27 '15 at 22:58

1 Answers1

2

pymatrix_to_CarrayptrsInt() calls ptrvectorInt() and this allocation is made
if (!(result[i] = malloc(dim2 * sizeof(int)))){
then pymatrix_to_CarrayptrsInt() writes over that allocation with this assignment
result[i] = &array[i * m];
causing a memory leak. If array is free()'d then attempting to free() result will fail

user3121023
  • 8,181
  • 5
  • 18
  • 16
  • I am not sure whether I understood you right. I understood you that way that the statement `if (!(result[i] = malloc(dim2 * sizeof(int))))` is unnecessary and even harmful. Furthermore, I do not need to run go over all entries of `ptr` and only have to free `ptr` itself. Hence, I deleted the respective lines (i.e. the `for`-loops in `ptrvectorInt` and `free_CarrayptrsInt`). My program worked fine and the memory usage remained constant. To me it looks as if the problem is solved that way. Were these the changes you suggested? Or am I still doing something wrong or risky? – Samufi May 27 '15 at 22:52
  • Thanks for the answer, @user3121023! `arrayin->data` is related to a python object whose memory is managed by python. Therefore, it will never be freed. Since performance is imprtant for my program, I prefer not to copy the values. – Samufi May 28 '15 at 00:00