How to correctly use malloc and free memory?
Asked Answered
M

7

7

I am wondering what is the right/standard way to use malloc and free. Is it needed to set pointer NULL after free? Basically, which of the two following ways is correct?

double* myPtr = (double*)malloc(sizeof(double)*5);
.....
free(myPtr);

or

double* myPtr = (double*)malloc(sizeof(double)*5);
.....
free(myPtr);
myPtr = NULL;

Or it should be other ways to use malloc and free? Thanks.

Moffatt answered 4/7, 2014 at 13:30 Comment(9)
You have to specify, either C or C++ ?Dunton
Setting the pointer to NULL does "help" in the situation where your workflow or a bug might try to free the buffer more than once.Orientalism
I would guess that scope would answer a lot of those questions. If they're local variables, the variable will disappear when the frame is popped off the stack.Piny
If this is C++, the answer is usually don't use malloc or free.Remonstrant
Thank you all of you. I really feel I learn about something that seems so straightforward but can be tricky many occasions.Moffatt
For C, please don't cast the return value of malloc(). I know simonc mentioned this below, but the linked-to answer has more words.Race
I see. I am using C++, so I guess it should be fine?Moffatt
@Moffatt If you are using C++ then don't tag C !Algebraist
@BlueMoon Care to elaborate a little? So don't use malloc you mean? If so what should I use?Moffatt
K
13

Both are fine. The only difference is that the former approach would crash if you tried to free myPtr a second time.

Depending on the language you're using, the malloc line could be tidied up a little.

Using sizeof(*myPtr) is less prone to bugs when you later refactor. If you're using C, the cast is also unnecessary

double* myPtr = malloc(sizeof(*myPtr)*5);

As pointed out by WhozCraig, if you're using C++, there are much easier ways to allocate an array

 std::vector<double> ar(5);

gives you an array of 5 doubles that will grow its storage if required and automatically free its memory when it goes out of scope.

Kidron answered 4/7, 2014 at 13:33 Comment(3)
@WhozCraig Thanks for fixing that important/embarrassing typo!Kidron
+1. Also, since sizeof is not a function, you can drop the parentheses. I format it like double *myPtr = malloc(5 * sizeof *myptr);, i.e. constant/scaling factor before the sizeof.Race
@Kidron =P glad to help, Followup to "If you're using C, the cast is also unnecessary.." - If you're using C++, the malloc itself is unnecessary =) std::vector<double> ar(5);.Harod
G
9

There is no any need to set the pointer to NULL in statement

myPtr = NULL;

On the one hand this prevents the program from an execution error if you will try to free the pointer the second time. On the other hand it maybe hides the bug code where you try to free the pointer the second time.

So whether you need to set the pointer to NULL depends on the program design.

If you are speaking about C++ then it would be better if you would use never C functions malloc and free. Consider using of smart pointers as for example std::shared_ptr.

Groome answered 4/7, 2014 at 13:37 Comment(0)
D
4

Use of free:

free() only marks the memory chunk as free - there is no enforcement of this freeing operation. Accessing memory chunks that were previously freed is the cause of many memory errors for novices and experienced programmers. A good practice is that always nullify a pointer that was just freed.

In case of C, just remove the cast:

double* myPtr = malloc(sizeof(double)*5);
.....
free(myPtr);
myPtr = NULL; 
Dunton answered 4/7, 2014 at 13:32 Comment(2)
The quoted passage is false; Ely has the correct answer with regards to nulling it. Things like myPtr = NULL; in such cases only give a false sense of confidence, and can easily hide errors.Desiderate
@JamesKanze; Stated clear there that: Accessing memory chunks that were previously freed, that mean if you do not want to access it then no need to nullify.Dunton
V
4

Setting the pointer back to "NULL" will only be useful if you need to reuse it again later and run checks on it like "if(myPtr) { [...] }". If you don't plan on reusing this specific pointer, you can leave it to whatever his value is.

Vermis answered 4/7, 2014 at 13:32 Comment(0)
P
2

What you write is correct (however in C you shouldn't cast the return value of malloc, but in C++ you must do the cast). You don't have to set myPtr to NULL after calling free. Just don't dereference the memory after if has been freed.

Piscatorial answered 4/7, 2014 at 13:33 Comment(1)
I am learning C++ now to translate some C code. I just found out about having to cast malloc(sizeof(int)) from void* to int* (or double). Nice to see it mentioned here.Handshaker
E
2

You are free to do with Your pointer anything. You don't MUST set it to NULL, but it's good if You don't want to get SEGFAULT for free.

Let see examples.

double * ptr = malloc(sizeof(double) * 42 );
ptr[0] = 1.2; // OK
free (ptr); // OK
ptr = malloc(sizeof(double) * 13); // It's OK. You don't need to set pointer to NULL

Let see some more examples.

void assign(ptr)
{
    if( ptr != NULL) ptr[0] = 1.2;
}

double * ptr = NULL;
assign(ptr); // All OK, method will not pass check
double * ptr = malloc(sizeof(double) * 42);
assign(ptr); // OK, method will pass check and assign
free(ptr);
// ptr = NULL; // If we don't do this ....
.... a lot of code and 666 lines below ... 
assign(ptr); // BAH! Segfault! And if You assign ptr=NULL, it would not a segfault
Enjoyment answered 4/7, 2014 at 13:35 Comment(3)
There are no guarantees on that segfaulting.Remonstrant
Yeah, and this is the worst part. Pure undefined behaviour. There are no guarantees on that will NOT segfaulting. You SHOULD NOT write to unallocated memory. Never.Enjoyment
sure :). Edited comment.Enjoyment
K
1

It is best to avoid malloc/free if you can avoid it. You can avoid it if

  • the array or structure you are allocating is "small" (you can count the size on your fingers) and you know the size at compile time

  • the array is used and discarded in the local scope of your program

If these are true, don't use malloc/free, but just use local auto variables which are allocated from the stack instead of the heap.

For example, this is simpler and easier to maintain

 {
   double myPtr[5];
   ...
 }

than this

 {
   double* myPtr = (double*)malloc(sizeof(double)*5);
   ...
   free(myPtr);
 }

It's good practice to use stack variables when you can, because a stack never gets "fragmented" like a heap can. But of course, a stack can overflow, so don't put anything "big" on the stack. Knowing what is "big" is not an exact science; you should know what your stack size is beforehand.

Kaput answered 7/7, 2014 at 20:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.