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.
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.
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.
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.
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;
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
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.
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.
Related
This Question statement is came in picture due to statement made by user (Georg Schölly 116K Reputation) in his Question Should one really set pointers to `NULL` after freeing them?
if this Question statement is true
Then How data will corrupt I am not getting ?
Code
#include<iostream>
int main()
{
int count_1=1, count_2=11, i;
int *p=(int*)malloc(4*sizeof(int));
std::cout<<p<<"\n";
for(i=0;i<=3;i++)
{
*(p+i)=count_1++;
}
for(i=0;i<=3;i++)
{
std::cout<<*(p+i)<<" ";
}
std::cout<<"\n";
free(p);
p=(int*)malloc(6*sizeof(int));
std::cout<<p<<"\n";
for(i=0;i<=5;i++)
{
*(p+i)=count_2++;
}
for(i=0;i<=3;i++)
{
std::cout<<*(p+i)<<" ";
}
}
Output
0xb91a50
1 2 3 4
0xb91a50
11 12 13 14
Again it is allocating same memory location after freeing (0xb91a50), but it is working fine, isn't it ?
You do not reuse the old pointer in your code. After p=(int*)malloc(6*sizeof(int));, p point to a nice new allocated array and you can use it without any problem. The data corruption problem quoted by Georg would occur in code similar to that:
int *p=(int*)malloc(4*sizeof(int));
...
free(p);
// use a different pointer but will get same address because of previous free
int *pp=(int*)malloc(6*sizeof(int));
std::cout<<p<<"\n";
for(i=0;i<=5;i++)
{
*(pp+i)=count_2++;
}
p[2] = 23; //erroneouly using the old pointer will corrupt the new array
for(i=0;i<=3;i++)
{
std::cout<<*(pp+i)<<" ";
}
Setting the pointer to NULL after you free a block of memory is a precaution with the following advantages:
it is a simple way to indicate that the block has been freed, or has not been allocated.
the pointer can be tested, thus preventing access attempts or erroneous calls to free the same block again. Note that free(p) with p a null pointer is OK, as well as delete p;.
it may help detect bugs: if the program tries to access the freed object, a crash is certain on most targets if the pointer has been set to NULL whereas if the pointer has not been cleared, modifying the freed object may succeed and result in corrupting the heap or another object that would happen to have been allocated at the same address.
Yet this is not a perfect solution:
the pointer may have been copied and these copies still point to the freed object.
In your example, you reuse the pointer immediately so setting it to NULL after the first call to free is not very useful. As a matter of fact, if you wrote p = NULL; the compiler would probably optimize this assignment out and not generate code for it.
Note also that using malloc() and free() in C++ code is frowned upon. You should use new and delete or vector templates.
I have read this post about check before calling free(). I want to further confirm through a case.
The following codes are copied from my C++ project (tested, no error/warning). I just want to confirm the right way to check memory allocation and free() in C++.
// part 1: declare
typedef struct cipher_params_t {
unsigned char * p1;
int p2;
}cipher_params_t;
// part 2: allocate memory
cipher_params_t *params = (cipher_params_t*)malloc(sizeof(cipher_params_t));
// part 3: check allocate memory
if (!params) {
/* Unable to allocate memory on heap*/
fprintf(stderr, "ERROR: malloc error: %s\n", strerror(errno));
return errno;
}
// part 4: assign values
unsigned char key[16] = {0x01, 0x02, ..., 0x0f};
params -> p1 = key;
params -> p2 = 1;
// part 5: use params for some function
some_func(params);
// part 6: free params lastly
cleanup1(params);
// cleanup2(params); //another option
void cleanup1 (cipher_params_t *params){
if(params) free(params)
}
void cleanup2 (cipher_params_t *params){
if(params!=NULL) free(params)
}
Questions:
In part 3, is this the correct way to check if(!params). Any error is not considered here?
In part 6, I give 2 options - if(params) and if(params!=NULL). Are they same?
In part 1, struct includes pointer(p1) and non-pointer(p2). What is the difference between free a pointer, free a non-pointer, and free a combination of both?
If I use delete[ ] instead of free(). How? and what's the difference?
In part 3, is this the correct way to check if(!params). Any error is not considered here?
Yes this is correct since malloc() returns NULL on failure.
In part 6, I give 2 options - if(params) and if(params!=NULL). Are they same?
Yes, they are the same. But in C++ there is several reasons to use nullptr (a proper type nullptr_t) instead of NULL.
In part 1, struct includes pointer(p1) and non-pointer(p2). What is the difference between free a pointer, free a non-pointer, and free a combination of both?
In fact, you don't and can't release a non-pointer. In your case, you are releasing only one pointer that is a pointer to a cipher_params_t structure.
With malloc() you allocates memory for containing a cipher_params_t whatever the contents is, you just allocate enough space for containing it. And when you free(), you release the allocated memory, no matter what the structure contains.
Please note that malloc() and free() don't call contructors/destructors, neither for the pointed structure, nor for its contents. They are just reserving/allocating memory space.
If I use delete[ ] instead of free(). How? and what's the difference?
Never ever mix malloc()/free(), new/delete and new[]/delete[] because they don't do the same thing. You should read What is the difference between new/delete and malloc/free? for more information.
Regarding the question:
In part 1, struct includes pointer(p1) and non-pointer(p2). What is
the difference between free a pointer, free a non-pointer, and free a
combination of both?
in the example you gave you are deleting a struct from heap mem. This struct has a pointer (assuming 8 bytes) and an int (usually 4 bytes) so you delete this piece of memory (12 bytes) and nothing else.
The memory where the pointer is pointing will remain there, so the key[16] won't be touched. In your example there is a possible issue, as params it's on heap and key is in stack, stack will be deleted when you leave scope but params pointer could still point to it.
I am trying to build a stack that resizes itself and realloc() crashes my program.
Constructor:
Stack::Stack()
{
st = (int*)malloc(sizeof(int));
sp = 0;
length = 1;
}
This is my add() function:
void Stack::add(int item)
{
if (sp == length)
Stack::resizeStack(&st, &length, 1);
st[sp++] = item;
}
Resize function (I use the variable a in order to be able to reuse it for pop) :
void Stack::resizeStack(int **st, int *length, bool a)
{
if (a == 1)
*length *= 2;
else
*length /= 2;
realloc(*st, sizeof(int) * (*length));
}
This is how I test my stack:
Stack* myStack = new Stack();
for (int i = 0; i < 10; i += 1) {
myStack->add(i);
cout << myStack->getStackSize() << '\n';
}
free(myStack);
I have noticed that the program crashes at the end of the for.
I would appreciate if someone explained what I am doing wrong.
All those people who say, malloc() and free() are a bad idea in C++ are 100% correct. Prefer new and delete over malloc() and free() and prefer standard library containers over your own homebrew stack implementation.
Anyway, the real issue here is, that realloc() might allocate a new memory block and free the old one. It returns a pointer to the new one.
The correct call is:
*st = realloc(*st, sizeof(int) * (*length));
Now *st will store the new pointer and everything is all right.
Consider to use the standard library, instead of implementing your own fundamental data structures. It has a well designed interface, and is very thoroughly tested.
You are lucky that you get a crash. This is undefined behavior.
Let's see what Bjarne Stroustrup says about this from here:
No, in the sense that you cannot allocate an object with malloc() and
free it using delete. Nor can you allocate with new and delete with
free() or use realloc() on an array allocated by new.
The C++ operators new and delete guarantee proper construction and
destruction; where constructors or destructors need to be invoked,
they are. The C-style functions malloc(), calloc(), free(), and
realloc() doesn't ensure that. Furthermore, there is no guarantee that
the mechanism used by new and delete to acquire and release raw memory
is compatible with malloc() and free(). If mixing styles works on your
system, you were simply "lucky" - for now.
C++ FAQ has also special entry for this:
https://isocpp.org/wiki/faq/freestore-mgmt#realloc-and-renew
Crashing at the end is most likely because you're mixing new with free. This is undefined behaviour. It may work on some systems, but is never a good idea. You should pair new with delete. Calls to malloc are paired with free, but these are more for C code. C++ code usually uses new and delete.
Of course you can eliminate the new by making myStack a local variable:
Stack myStack;
You would also need to adjust member access to use . instead of ->. There would be no need to delete myStack, since local variables would be automatically cleaned up once the function exits, including in the case of exceptions.
Also noticed the return value of realloc is ignored. If the current memory block can't be extended by realloc, it must allocate a new memory block and copy the old data over to it. A new pointer is returned in this case, so st must be updated.
*st = realloc(*st, sizeof(int) * (*length));
But again, using malloc, realloc, and free is a bit odd in C++ code.
You can use new[] and delete[] if you're forced to use manual memory management of arrays (such as for learning), or you can use the vector or stack classes for more serious code.
Use std::vector and it will automatically take care of all the memory management for you. In fact, you pretty much just don't need a Stack class in the face of std::stack but that's another matter.
Furthermore for the test do not allocate the Stack dynamically in a super pointless way, just make a local Stack.
I'm returning an void* pointer to a chunk in memory in this function:
memory.cpp:
int mem[1000];
int* pointers[100];
int start_index = 100;
void* allocate(int size) {
pointers[0] = &mem[start_index];
return (void *) pointers[0];
}
main.cpp:
int* arr = (int*) allocate(50); // allocate array of size 50 starting at mem[100]
arr[0] = 62; // changes mem[100] to 62
Now say I wanna make the user of this function use different location of mem array, without the user of allocate function being notified (assuming it'd be no problem we lose the data).
Can't I do this?
memory.cpp:
pointers[0] = &mem[200];
After this line is executed in memory.cpp, I want arr[0] point to mem[200].
Is that possible without changing the prototype of allocate function?
Thanks
No, you can't. You would need to return a pointer-to-a-pointer (void**) and make it absolutely clear to clients of the allocate function that they are not allowed to create aliases to the memory. Anyways, this is a very bad idea, you'll run into problems left and right (e.g. what if your client uses in-place new to allocate a non-POD object in that memory?)
Yes you can change a pointer to point at something else anytime.
However, this will only change the pointer you assign to, not other places using the old pointer. So if some code saves the returned value from your allocate function, and you later change pointers[0] to point to something else, the old saved pointer will not change.
void aFunction_2()
{
char* c = new char[10];
c = "abcefgh";
}
Questions:
Will the: c = "abdefgh" be stored in the new char[10]?
If the c = "abcdefgh" is another memory area should I dealloc it?
If I wanted to save info into the char[10] would I use a function like strcpy to put the info into the char[10]?
Yes that is a memory leak.
Yes, you would use strcpy to put a string into an allocated char array.
Since this is C++ code you would do neither one though. You would use std::string.
void aFunction_2()
{
char* c = new char[10]; //OK
c = "abcefgh"; //Error, use strcpy or preferably use std::string
}
1- Will the: c = "abdefgh" be
allocated inner the new char[10]?
no, you are changing the pointer from previously pointing to a memory location of 10 bytes to point to the new constant string causing a memory leak of ten bytes.
2- If the c = "abcdefgh" is another
memory area should I dealloc it?
no, it hasn't been allocated on heap, its in read-only memory
3- If I wanted to save info inner the
char[10] I would use a function like
strcpy to put the info inner the
char[10]?
not sure what you mean with 'inner' here. when you allocate using new the memory is allocated in the heap and in normal circumstances can be accessed from any part of your program if you provide the pointer to the memory block.
Your answer already has been answered multiple times, but I think all answers are missing one important bit (that you did not ask for excplicitly):
While you allocated memory for ten characters and then overwrote the only pointer you have referencing this area of memory, you are created a memory leak that you can not fix anymore. To do it right, you would std::strcpy() the memory from the pre-allocated, pre-initialized constant part of the memory where the content of your string-literal has been stored into your dynamically allocated 10 characters.
And here comes the important part:
When you are done with dealing with these 10 characters, you deallocate them using delete[]. The [] are important here. Everything that you allocate using new x[] has to be deallocated with delete[]. Neither the compiler nor the runtime warn you when use a normal delete instead, so it's important to memorize this rule.
No, that is only pointer reassignment;
No, deleteing something that didn't come from new will often crash; and
Yes, strcpy will do the job… but it's not usually used in C++.
Since nobody has answered with code, std::uninitialized_copy_n (or just std::copy_n, it really doesn't make a difference here) is more C++ than strcpy:
#include <memory>
static char const abcs[] = "abcdefgh"; // define string (static in local scope)
char *c = new char[10]; // allocate
std::copy_n( abcs, sizeof abcs, c ); // initialize (no need for strlen)
// when you're done with c:
delete[] c; // don't forget []
Of course, std::string is what you should use instead:
#include <string>
std::string c( "abcdefgh" ); // does allocate and copy for you
// no need for delete when finished, that is automatic too!
No (pointer reassignment)
No
Yes, you can use strcpy(), see for instance: