Let's suppose I have this code:
for (int i=0;i<n;i++) {
//compute z
float *p = (float *) malloc (sizeof(float)*z);
//do something with p
}
Notice that p isn't used anywhere else and each for cycle is independent from the other.
Let's suppose that z is not so big, so the single p is not that expensive in terms of memmory. However, n is potentially big, so the total memory taken by p can be consistent.
Is it correct to free() it with:
for (int i=0;i<n;i++) {
//compute z
float *p = (float *) malloc (sizeof(float)*z);
//do something with p
free(p);
}
Bonus question: if time performance would be the priority (and not memory consumption), would be better to avoid the free(p), since it's time consuming?
Since you tagged this with C++, you should never use malloc and free. Use smart pointers (or new/delete if you don't have access to a C++11-compliant compiler).
for (int i=0;i<n;i++) {
// compute z
std::unique_ptr<float[]> p{new float[z]};
// do something with p
// p gets automatically freed at the end of the scope
}
To answer your questions:
Is it correct to free() it with...
Yes. If you allocate something with malloc, you always need to free it.
would be better to avoid the free(p), since it's time consuming?
Yes. Consider preallocating the memory location outside of the loop.
// preallocate
std::unique_ptr<float[]> p{new float[z]};
for (int i=0;i<n;i++) {
// clear p
// compute z
// do something with p
}
// p gets automatically freed at the end of the scope
You can pre-allocate necessary memory amount before the cycle and re-use it.
In case if you don't know how big z would be - I would recommend to write size of allocated memory somewhere, and if z is bigger than it - then re-allocate, else - just re-use already allocated memory.
Observe: malloc is used. Act: invoke free. It's as simple as that. Portable, well-defined code requires malloc and free.
The amount of memory allocated plays no role here. If it's too much memory, malloc will throw an error, but that has nothing to do with the fact that you always need a free to follow a malloc.
Yes. You must free it. Otherwise you have a memory leak, which is bad. Especially if you loop a large number of times.
A good rule of thumb is that every malloc must be matched by a free. Always. (this is especially important on larger projects)
Consider using a buffer, that is reused in order to avoid unnecessary allocations. This can be done very easily by using std::vector<float>:
std::vector<float> p;
for (int i=0;i<n;i++) {
//compute z
p.resize( z );
//do something with p
}
In the worst case you get O(log n) memory allocations. With your code you will get n memory allocations. Not calling free() just causes a memory leak. std::vector<float> will clean up the memory automatically eventually.
It seems the size is constant, so why you want to allocate it again and again?
Just allocate once before the loop, inside the loop initialise at the beginning.
You can reuse the memory. And after the loop ends free the memory.
And the program ends after the loop then you don't have to free it, all the heap memory that the program consumed would be returned to the OS, but it is always a good practice to free the memory you allocate.
On the bonus question, free is not that time consuming but allocating memory is, so don't worry on the time consumed by free.
If you reuse that memory again - it is obviously more efficient to free it only when you end your program and only allocated it once (and reallocate using realloc() when you need bigger/smaller array).
Every OS you will probably program for will handle releasing dynamically allocated memory when your program terminates. But, as we mostly try to keep our code as cross-platform as possible, you should always free() dynamically allocated memory.
As for if you have a huge amount of memory and care only for speed - then obviously free()ing would 'slow down' the program, but the amount of time it takes is so ridiculously small, 76*(10**-8) on my humble machine, for a 1024 bytes chunk, so it is fairly insignificant.
Related
I'm just starting to learn coding in c, and I have a few questions regarding 2d matrices in combination with the free() command.
I know that you first need to create an array with pointer, pointing to the different columns of the matrix:
double **array = (double **)malloc(5*sizeof(double *));
for(int n = 0; n<5; n++){
array[n] = (double *) malloc(6*sizeof(double));
I know that the correct way to then deallocate this matrix is to first deallocate the individual rows and then the array pointer itself. Something along the lines of:
for (i = 0; i < nX; i++){
free(array[i]); }
free(array);
My question is: Why is this necessary? I know that this incorrect, but why can't you just use: free(array)? This would deallocate the pointer array, to my understanding. Won't the memory that is used by the columns just be overwritten when something else needs acces to it? Would free(array) lead to corrupted memory in any way?
Any help is much appreciated!
Your code, not only allocate memory for array of pointers (the blue array), but in the for loop, you also allocate memory for the red arrays as well. So, free(array) line, alone, will just free the memory allocated by the blue array, but not the red ones. You need to free the red ones, just before loosing the contact with them; that is, before freeing the blue array.
And btw;
Won't the memory that is used by the columns just be overwritten when something else needs acces to it?
No. The operating system will keep track of the memory allocated by your process (program) and will not allow any other process to access the allocated memory until your process terminates. Under normal circumstances —I mean, remembering the C language not having a garbage collector— the OS never knows that you've lost connection with the allocated memory space and will never attempt like, "well, this memory space is not useful for this process anymore; so, let's de-allocate it and serve it for another process."
It would not lead to corruption, no, but would create a memory leak.
If done once in your program, it probably doesn't matter much (a lot of professional/expensive applications have - small,unintentional - memory leaks), but repeat this in a loop, and you may run out of memory after a while. Same thing if your code is called from an external program (if your code is in a library).
Aside: Not freeing buffers can be a useful way (temporarily) to check if the crashes you're getting in your programs originate from corrupt memory allocation or deallocation (when you cannot use Valgrind). But in the end you want to free everything, once.
If you want to perform only one malloc, you could also allocate one big chunk, then compute the addresses of the rows. In the end, just deallocate the big chunk (example here: How do we allocate a 2-D array using One malloc statement)
This is needed because C does not have a garbage collector.
Once you allocate memory with malloc or similar function, it is marked as "in use" for as long as your program is running.
It does not matter if you no longer hold a pointer to this memory in your program.
There is no mechanism in the C language to check this and automatically free the memory.
Also, when you allocate memory with malloc the function does not know what you are using the memory for. For the allocator it is all just bytes.
So when you free a pointer (or array of pointers), there is no logic to "realize" these are pointers that contain memory addresses.
This is simply how the C language is designed: the dynamic memory management is almost1 completely manual - left to the programmer, so you must call free for every call to malloc.
1 C language does handle some of the more tedious tasks needed to dynamically allocate memory in a program such as finding where to get a free continuous chunk of memory of the size you asked for.
Let's take this simple example:
int **ptr = malloc(2*sizeof *ptr);
int *foo = malloc(sizeof *foo);
int *bar = malloc(sizeof *bar);
ptr[0] = foo;
ptr[1] = bar;
free(ptr);
If your suggestion were implemented, foo and bar would now be dangling pointers. How would you solve the scenario if you just want to free ptr?
The following code shows an example that repeatedly allocates memory without first calling free. Instead, it frees **sign after the loop.
#include <stdio.h>
#include <stdlib.h>
float ** fun(int nloc)
{
float **sign;
int i,nt=100,it,k;
sign=(float **)calloc(nloc,sizeof(float *));
for (i=0;i<nloc;i++)
sign[i] = (float *)calloc(nt,sizeof(float *));
for (it=0;it<nt;it++){
for (k=0;k<nloc;k++){
sign[k][it]=it*0.2;
}
}
return sign;
}
int main(int argc, char *argv[])
{
int i,isrc,n=3,nloc=1;
float **sign=NULL;
for (isrc=0;isrc<n;isrc++){
sign = fun(nloc);
}
for (i=0;i<nloc;i++){
free(sign[i]);
}
free(sign);
exit(0);
}
This is a correct code snippet. My question is: why is it legal that we can allocate memory for a pointer in each iteration without having to free it first?
[Supplementary message]:
Hi all, I think there's one case we cannot free memory in the loop. If buffer=p and p is defined outside the loop, like:
float *buffer, *p;
/* Elements of p calculated */
for (...){
/* allocate memory for **buffer */
buffer = p;
free(buffer)
/* if free here will cause p lost */
}
If free buffer at the end of each loop, it may cause p lost because buffer and p share the same memory address.
why is it legal that we can allocate memory for a pointer in each iteration without having to free it first?
The responsibility of freeing dynamically allocated memory is left on the programmer. It is legal because the compiler does not enforce it, although there are code checking tools that can flag this problem.
Freeing dynamically allocated memory should be done in the reverse order of allocation. For ex:
for (i=0;i<nloc;i++)
free(sign[i]);
free(sign);
It is legal because in C, you as the programmer are responsible for memory management. There is a very good reason for this. To quote another thread
Garbage collection requires data structures for tracking allocations
and/or reference counting. These create overhead in memory,
performance, and the complexity of the language. C++ is designed to be
"close to the metal", in other words, it takes the higher performance
side of the tradeoff vs convenience features. Other languages make
that tradeoff differently. This is one of the considerations in
choosing a language, which emphasis you prefer.
Not only is performance and code size a consideration, but different systems have difference addressing schemes for memory. It is also for this reason that C is easy to port and maintain across platforms, given that there is no garbage collection to alter.
EDIT: Some answers mention freeing memory space as opposed to the pointer itself, it is worth further specifying what that means: free() simply marks the allocated space as available, it is not 'freed' or erased, nor does any other operation occur on that memory space. It is then still incumbent on the programmer to delete the address that was assigned to the pointer variable.
My question is: why is it legal that we can allocate memory for a pointer in each iteration without having to free it first?
Short answer
C trades away safety to gain simplicity and performance.
Longer answer
You don't free the pointer. You free the memory block the pointer is pointing at.
Think about what malloc (and calloc) does. They both allocate a piece of memory, and if the allocation is successful they return a pointer to that memory block. The allocation functions (like all functions) has no insight, nor control whatsoever of what you do with the return value. The functions does not even see the pointer that you are assigning the return value to.
It would be fairly complex (relatively speaking, C has a pretty simple structure) to implement a protection against it. First, consider this code:
int * a = malloc(1);
int * b = a;
a = malloc(1);
free(b);
free(a);
This code has no memory leaks, even though we did the precise thing you asked about. We reassigned a before calling free upon the memory from the first malloc. It works fine, because we have saved the address in b.
So in order to disallow reassigning pointers that points to a memory block that no other pointer points at, the runtime environment would need to keep track of this, and it is not entirely trivial. And it would also need to create extra code to handle all this. Since this check needs to be done at runtime, it may affect performance.
Also, remember that even though C may seem very low level today, it was considered a high level language when it came.
From what I understand, the malloc function takes a variable and allocates memory as asked. In this case, it will ask the compiler to prepare memory in order to fit the equivalence of twenty double variables. Is my way of understanding it correctly, and why must it be used?
double *q;
q=(double *)malloc(20*sizeof(double));
for (i=0;i<20; i++)
{
*(q+i)= (double) rand();
}
You don't have to use malloc() when:
The size is known at compile time, as in your example.
You are using C99 or C2011 with VLA (variable length array) support.
Note that malloc() allocates memory at runtime, not at compile time. The compiler is only involved to the extent that it ensures the correct function is called; it is malloc() that does the allocation.
Your example mentions 'equivalence of ten integers'. It is very seldom that 20 double occupy the same space as 10 int. Usually, 10 double will occupy the same space as 20 int (when sizeof(int) == 4 and sizeof(double) == 8, which is a very commonly found setting).
It's used to allocate memory at run-time rather than compile-time. So if your data arrays are based on some sort of input from the user, database, file, etc. then malloc must be used once the desired size is known.
The variable q is a pointer, meaning it stores an address in memory. malloc is asking the system to create a section of memory and return the address of that section of memory, which is stored in q. So q points to the starting location of the memory you requested.
Care must be taken not to alter q unintentionally. For instance, if you did:
q = (double *)malloc(20*sizeof(double));
q = (double *)malloc(10*sizeof(double));
you will lose access to the first section of 20 double's and introduce a memory leak.
When you use malloc you are asking the system "Hey, I want this many bytes of memory" and then he will either say "Sorry, I'm all out" or "Ok! Here is an address to the memory you wanted. Don't lose it".
It's generally a good idea to put big datasets in the heap (where malloc gets your memory from) and a pointer to that memory on the stack (where code execution takes place). This becomes more important on embedded platforms where you have limited memory. You have to decide how you want to divvy up the physical memory between the stack and heap. Too much stack and you can't dynamically allocate much memory. Too little stack and you can function call your way right out of it (also known as a stack overflow :P)
As the others said, malloc is used to allocate memory. It is important to note that malloc will allocate memory from the heap, and thus the memory is persistent until it is free'd. Otherwise, without malloc, declaring something like double vals[20] will allocate memory on the stack. When you exit the function, that memory is popped off of the stack.
So for example, say you are in a function and you don't care about the persistence of values. Then the following would be suitable:
void some_function() {
double vals[20];
for(int i = 0; i < 20; i++) {
vals[i] = (double)rand();
}
}
Now if you have some global structure or something that stores data, that has a lifetime longer than that of just the function, then using malloc to allocate that memory from the heap is required (alternatively, you can declare it as a global variable, and the memory will be preallocated for you).
In you example, you could have declared double q[20]; without the malloc and it would work.
malloc is a standard way to get dynamically allocated memory (malloc is often built above low-level memory acquisition primitives like mmap on Linux).
You want to get dynamically allocated memory resources, notably when the size of the allocated thing (here, your q pointer) depends upon runtime parameters (e.g. depends upon input). The bad alternative would be to allocate all statically, but then the static size of your data is a strong built-in limitation, and you don't like that.
Dynamic resource allocation enables you to run the same program on a cheap tablet (with half a gigabyte of RAM) and an expensive super-computer (with terabytes of RAM). You can allocate different size of data.
Don't forget to test the result of malloc; it can fail by returning NULL. At the very least, code:
int* q = malloc (10*sizeof(int));
if (!q) {
perror("q allocation failed");
exit(EXIT_FAILURE);
};
and always initialize malloc-ed memory (you could prefer using calloc which zeroes the allocated memory).
Don't forget to later free the malloc-ed memory. On Linux, learn about using valgrind. Be scared of memory leaks and dangling pointers. Recognize that the liveness of some data is a non-modular property of the entire program. Read about garbage collection!, and consider perhaps using Boehm's conservative garbage collector (by calling GC_malloc instead of malloc).
You use malloc() to allocate memory dynamically in C. (Allocate the memory at the run time)
You use it because sometimes you don't know how much memory you'll use when you write your program.
You don't have to use it when you know thow many elements the array will hold at compile time.
Another important thing to notice that if you want to return an array from a function, you will want to return an array which was not defined inside the function on the stack. Instead, you'll want to dynamically allocate an array (on the heap) and return a pointer to this block:
int *returnArray(int n)
{
int i;
int *arr = (int *)malloc(sizeof(int) * n);
if (arr == NULL)
{
return NULL;
}
//...
//fill the array or manipulate it
//...
return arr; //return the pointer
}
I have a function in which I make use of a local array. I would like to return a pointer to this, but of course one cannot do this unless one manually allocates memory. Therefore I would like to know if allocation like so:
for(i = 0; i < 26; i++)
{
llist[i] = malloc(sizeof(SomeStruct));
}
can be later freed like so:
// (where ptr is a pointer to the first allocation in llist)
for(i = 0; i < 26, i++)
{
free(ptr);
ptr += sizeof(SomeStruct);
}
Edit:
Seems I can't do this. Is there any way in which I could free all the memory given only a pointer to the first element? Or should I take a different approach entirely?
No, it cannot. There is no guarantee that these blocks are allocated consecutively. In fact, they are almost certainly not with all the modern implementations I've seen. Most store the size of the block and often other information immediately before each block. Also, if your memory is fragmented, the blocks might wind up anywhere in the free space between other data, where there is not sufficient room to place them consecutively.
No, you can't. In the first empty space malloc finds it might only be place for one struct. If that's the case, the next block will be placed somewhere else.
Depends on what you do inside the loop. Some functions will allocate buffers internally, which means that malloc() could be called behind your back. In your simple loop, the values SHOULD be consecutive. As well, once you throw in multi-threading, all bets are out the window, as something in another thread could malloc() memory as well.
The actual allocation spot also depends on how fragmented your memory is. There may not be enough consecutive blocks to handle your request, so the actual allocation could be from anywhere in the free space.
Here is what I am working with:
char* qdat[][NUMTBLCOLS];
char** tdat[];
char* ptr_web_data;
// Loop thru each table row of the query result set
for(row_index = 0; row_index < number_rows; row_index++)
{
// Loop thru each column of the query result set and extract the data
for(col_index = 0; col_index < number_cols; col_index++)
{
ptr_web_data = (char*) malloc((strlen(Data) + 1) * sizeof(char));
memcpy (ptr_web_data, column_text, strlen(column_text) + 1);
qdat[row_index][web_data_index] = ptr_web_data;
}
}
tdat[row_index] = qdat[col_index];
After the data is used, the memory allocated is released one at a time using free().
for(row_index = 0; row_index < number_rows; row_index++)
{
// Loop thru all columns used
for(col_index = 0; col_index < SARWEBTBLCOLS; col_index++)
{
// Free memory block pointed to by results set array
free(tdat[row_index][col_index]);
}
}
Is there a way to release all the allocated memory at once, for this array?
Thank You.
Not with the standard malloc() allocator - you need to investigate the use of memory pools. These work by allocating a big block of memory up-front, allocating from it and freeing back to it as you request via their own allocation functions, and then freeing the whole lot with a special "deallocate all" function.
I must say I've always found these things a bit ugly - it really isn't that hard to write code that doesn't leak. The only reason I can see for using them is to mitigate heap fragmentation, if that is a real problem for you.
No there is not. Memory which is separately allocated must be separately freed.
The only way you could free it as once is if you allocated it at once is a giant block. You would then have to do a bit of pointer math to assign every row the correct index into the array but it's not terribly difficult. This approach does have a few downsides though
Extra pointer math
Requires one giant contiguous block of memory vs. N smaller blocks of memory. Can be an issue in low memory or high fragmentation environments.
Extra work for no real stated gain.
If you want to release it all at once, you have to allocate it all at once.
A simple manual solution, if you know the total size you'll need in advance, is to allocate it all in once chunk and index into it as appropriate. If you don't know the size in advance you can use realloc to grow the memory, so long as you only access it indexed from the initial pointer, and don't store additional pointers anywhere.
That being said, direct allocation and deallocation is a simple solution, and harder to get wrong than the alternatives. Unless the loop to deallocate is causing you real difficulties, I would stick with what you have.