简体   繁体   中英

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?

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 fe:

#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!

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.

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.

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);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM