Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When is it necessary to allocate dynamic memory using malloc on pointers?

Tags:

c

pointers

malloc

I am having trouble fully understanding the malloc() function in C, more precisely when it is necessary to use it.

When I declare a pointer to a global struct like so,

struct Position* currentPositionPtr;

do I need to assign dynamic memory to it using malloc to initialize it? Or is it good practice to simply assign a pointer of the struct to it later on when needed like e.g.

currentPositionPtr = getPosition();

where getPosition() returns a pointer to the "struct Position".

like image 895
noe Avatar asked Jan 31 '26 21:01

noe


2 Answers

What does getPosition() do?

If it returns a valid pointer to struct Position, then of course you don't need to allocate memory for the struct twice. I hope your function does not look like this:

struct Position *getPosition()
{
    struct Position p = { x, y };
    return &p;
}

since this would exhibit undefined behavior (by returning a pointer to a block scope automatic object). Generally, you rather return an already malloc()ated pointer instead:

struct Position *getPosition()
{
    struct Position *p = malloc(sizeof(*p));
    p->x = 42;
    p->y = 1337;
    return p;
}

Then, again, you don't need an additional call to malloc().

If, however, it's not the called function who is responsible for the allocation, then, well... it's the caller who is:

void getPosition(struct Position *p)
{
    p->x = 42;
    p->y = 1337;
}

And in this latter case you would need to call it like this:

struct Position *p = malloc(sizeof(*p));
getPosition(p);

if you need your struct to survive function returns, or

struct Position p;
getPosition(&p);

if you don't.

malloc (or another memory-allocating function) is needed whenever you need the system to give memory to you.

So yes, when you do

struct Position* currentPositionPtr;

you will either need a call to malloc():

currentPositionPtr = malloc(sizeof(struct Position));

or to assign the pointer to the address of an already allocated block of memory:

struct Position globalPos;

void func(void) {
    struct Position pos;
    struct Position* currentPositionPtr = &pos; //ok
    struct Position* globalPosPtr = &globalPos; //also ok
    ...
}

because all you are doing is declaring the pointer, not reserving space for a structure.

However, if your pointer is global, assigning it to stack-allocated memory is potentially dangerous. Consider the following:

struct Position *globalPosPtr = NULL;

void foo(void) {
    struct Position pos;
    globalPosPtr = &pos;
    //can dereference globalPosPtr with no problems here
    ...
}

void bar(void) {
    foo();
    //globalPosPtr is invalid here
    ...
}

As for your question about having another function that returns a pointer:

getPosition() will need to use malloc or some other memory-allocating function itself. So doing that is perfectly fine, and can make sense if you generally want to initialize values in the struct to some values. However, remember that, even if you called malloc inside some other function, you will need to free the memory when you are done using it to prevent memory leaks.

To answer the question in the title, whenever you declare something as a pointer, you need to give it something to point at if you want to use it. If you want it to point at a new thing, you need to dynamically allocate it with malloc() or a related function.

like image 45
Eric Finn Avatar answered Feb 03 '26 23:02

Eric Finn