Leon
Leon

Reputation: 364

How to dynamically allocate memory in a function?

Say I want to dynamically allocate memory but with a function instead of in the main() function.

So I tried to do this:

dynamAlloc(int *fPtr)
{
   fPtr=malloc(cols * sizeof(*fPtr) );
   if(fPtr==NULL)
    { 
      printf("Can't allocate memory");
      exit(1);
    }
}

Then I realised: Even though memory allocated on the heap is available for the lifetime of program, that memory can only be referenced by formal argument fPtr and not the actual argument(let's call it aPtr). But once, function is exited, that memory is lost.

So how then do I dynamically allocate memory with a function?

Upvotes: 1

Views: 1939

Answers (4)

August Karlstrom
August Karlstrom

Reputation: 11377

It's more convenient to use a macro function, like this:

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

#define NEW_ARRAY(ptr, n) \
    { \
        (ptr) = malloc((size_t) (n) * sizeof (ptr)[0]); \
        if ((ptr) == NULL) { \
            fputs("Can't allocate memory\n", stderr); \
            exit(EXIT_FAILURE); \
        } \
    }

#define NEW(ptr) NEW_ARRAY((ptr), 1)

int main(void)
{
    int *myArray;
    const int myArrayLen = 100;
    int i;

    NEW_ARRAY(myArray, myArrayLen);
    for (i = 0; i < myArrayLen; i++) {
        /*...*/
    }
    return 0;
}

Update:

The purpose of the macro is to abstract away the details and make memory allocation less error prone. With a (non-macro) function we would have to pass the element size as a parameter as that information is lost when a pointer is passed to a formal parameter of type void pointer:

void NewArray(void *ptr, int n, int elemSize)
{
        *ptr = malloc((size_t) n * sizeof elemSize);
        if (*ptr == NULL) {
            fputs("Can't allocate memory\n", stderr);
            exit(EXIT_FAILURE);
        }
}

With the function NewArray the allocation call corresponding to the first example becomes

NewArray(&myArray, n, sizeof myArray[0]);

which doesn't buy us much.

Upvotes: 0

that memory can only be referenced by formal argument fPtr and not the actual argument(let's call it aPtr).

aPtr cannot denote to the heap memory object before the call to dynamAlloc() because the object has not been allocated yet and its address assigned to aPtr trough fPtr. Thereafter aPtr do reference the heap object.

We just need to pass the address of the pointer of aPtr to dynamAlloc(). So you need appropriate arguments(actual arguments) and parameters (formal arguments) to pass the address of the pointer aPtr between the functions, like you see below.

So how then do I dynamically allocate memory with a function?

You do it like you do it main(), doesn´t matter if the pointer was declared inside of main() or another function, you just need to pass the address of the pointer aPtr to the other functions, in which you want to use the heap memory object, like f.e.:

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

#define cols 5

void dynamAlloc(int** fPtr);

int main()
{
    int* aPtr;

    dynamAlloc(&aPtr);

    free(aPtr);

    return 0;
}


void dynamAlloc(int** fPtr)                 
{
   *fPtr = malloc(sizeof(*fPtr) * cols);
   if(*fPtr == NULL)
    { 
      printf("Can't allocate memory");
      exit(1);
    }
}

Do not forget to free() the heap memory!

Upvotes: 2

0___________
0___________

Reputation: 67476

As you need to change the pointer itself - pointer to pointer is needed

void *allocate(void **tmp, size_t size)
{
    if(tmp)
    {
        *tmp = malloc(size);
    }
    return *tmp;
}


int main()
{
    int *ptr;

    if(!allocate((void**)&ptr, sizeof(*ptr) * 100))
    {
        perror("Error\n");
        exit(1);
    }
    /* do something*/
    free(ptr);
}

Upvotes: 0

Johny Siemano Kolano
Johny Siemano Kolano

Reputation: 137

or just make it like this:

void dynamAlloc(int **fPtr)
{
   *fPtr=malloc(cols * sizeof(**fPtr) ); // malloc is returning void* so in that place it would be compiler error, so pointer returned from malloc should be casted to the pointer type of the value.
   if(*fPtr==NULL) // that would be a warning in gcc since NULL is a macro eq to 0, or (void*)0, it compiler version
    { 
      printf("Can't allocate memory");
      exit(1);
    }
}

and the fuction usage:

int* ptr = (int*)NULL;
dynamAlloc(&ptr);
*ptr = 1; // assign 1 to the first element, ptr is a valid pointer here

but double pointer syntax can turn out slow in some conditions, answer with return in the end od fucntion, copy of that local pointer is better practise.

Upvotes: 1

Related Questions