1

i wonder if am correctly allocating and freeing memory. Am i allocating just the right amount of memory? Is the free() used as it should be? In next step i am supposed to reallocate memory for array with more rows ... any hint how realloc would look like?

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

#define cols        2

int** allocArray (unsigned int cap)
{
int** p;
unsigned int i;
p = (int **)malloc(sizeof(p)*cap);
for (i=0;i<cap;i++) {
    *(p+i) = (int *)malloc(sizeof(*p)*cols);
}
return p;
}

void freeArray (int** p, unsigned int cap)
{
int i;
for (i=0;i<cap;i++) {
    free(*(p+i));
}
free(p);
}

int main(void)
{
int** arr;
unsigned int cap = 2;

arr = allocArray(cap);
freeArray(arr,cap); 

return 0;
}

Thanks a lot for any input.

artm
  • 17,291
  • 6
  • 38
  • 54
703
  • 63
  • 1
  • 7
  • looks ok, except don't cast return type of `malloc`. – artm Dec 09 '15 at 19:47
  • 1
    If `p` is a pointer to a pointer to `int`, then `*p` is a pointer to `int`, so you're probably allocating more memory than you need. Oh, and [in C you should not cast the result of `malloc`](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc). Also note that just because you have a pointer, you can still use array indexing syntax, for any array *or pointer* `p` and index `i`, the expression `*(p + i)` is equivalent to `p[i]`. – Some programmer dude Dec 09 '15 at 19:48
  • Looks good, have you tested the program with valgrind r another tool? – Ryan Fitzpatrick Dec 09 '15 at 19:48
  • I used valgrind and it shows no errors. However i suspected that i am allocating more memory than needed. @Joachim - can you please suggest how to edit it? – 703 Dec 09 '15 at 19:59
  • How about e.g. `p = malloc(sizeof(*p) * cap);` for the outer array, and in the loop e.g. `p[i] = malloc(sizeof(*p[i]) * cols);`. – Some programmer dude Dec 10 '15 at 05:17

1 Answers1

1

This isn't really an answer, but it's too long for a comment - especially with the example code.

One easy optimization is to do just one allocation for the entire data area of a multi-dimensional array, and create arrays as necessary for the pointers into the data array. This will dramatically reduce the number of separate memory allocations - which can be important as the size of the array increases. Reducing the number of dynamic allocations that use malloc() (or new in C++) can also be extremely important for multithreaded applications as memory allocations tend to be single-threaded to a very large degree even for allocators targeted for multithreaded use.

You can do a 2-dimensional array with only two allocations:

int **alloc2IntArray( size_t m, size_t n )
{
    // get an array of pointers
    int **array = malloc( m * sizeof( *array ) );
    if ( NULL == array ) // I do this in case I mistype "==" as "="
    {
        return( NULL );
    }

    // get the actual data area of the array
    // (this gets all rows in one allocation)
    array[ 0 ] = malloc( m * n * sizeof( **array ) );
    if ( NULL == array[ 0 ] )
    {
        free( array );
        return( NULL );
    }

    // fill in the array of pointers
    // start at 1 because array[ 0 ] already
    // points to the 0th row
    for ( size_t i = 1U; i < m; i++ )
    {
        // use extra parenthesis to make it
        // clear what's going on - assigning the
        // address of the start of the i-th
        // row in the data area that array[ 0 ]
        // points to into the array of pointers,
        // which array points to (array[ 0 ]
        // already points to the 0th row)
        array[ i ] = &( ( array[ 0 ] )[ i * n ] );
    }

    return( array );
}

and

void free2dIntArray( int **array )
{
    free( array[ 0 ] );
    free( array );
}

You can use the same technique for an arbitrary number of dimensions, such that an N-dimensional array can be allocated with just N allocations.

And if you really want to, you can reduce the number of allocations down to just one - but then you have to worry about size of pointers and the alignment of all the elements.

Andrew Henle
  • 32,625
  • 3
  • 24
  • 56