Why use fixed length allocation instead of static allocation? - c

I understand that what I'm asking may be quite simple for some of you, but bear with me, I'm trying to understand memory management. Since we use a certain fixed length (N) for the size, why we also do this:
int *arr = (int*)malloc(N * sizeof(int))
..instead of the conventional static way:
int arr[N];

malloc provides memory that remains available after execution of the block it is in ends, such as when the function it is in returns.
int A[N], if it appears inside a function, uses memory that is guaranteed to be available only while execution of the block it is in has not ended. If it appears outside a function, the memory is available for all of program execution, but N must be a constant. (Further, even inside a function, int A[N] where N is not a constant is not supported in some C implementations.)
In typical C implementations in general-purpose operating systems, malloc has a large amount of memory available to provide, but int A[N] inside a function uses a stack region that is limited, commonly one to eight mebibytes total, depending on the system.

int arr[N]; goes either into static memory if it's in filescope (or is preceded by static) or on the stack.
A static-memory int arr[N]; is cheapest to allocate (both in terms of size overhead and allocation time) but it can never be freed and the memory won't always be cache-local.
If the int arr[N]; is inside a block (and not preceded by static), int arr[N]; goes on the stack. This memory will pretty much certainly be cache-local, but you might not wish to use this form if N is large and your stack is limited (or you're risking stack overflow) or if the lifetime of arr needs to exceed that of its containing block.
malloc'd memory takes some time to allocate (tens to hundreds of ns), it may carry some size overhead, and the allocation may fail, but you can free the memory later and it stays until you do free it. It might also be resizable (via realloc) without the need to copy memory. Cache-locality-wise, it's sort of like static memory (i.e., the block may be potentially far from the cache-hot end of the stack).
So those are the considerations: lifetime, stack size, allocation time, size overhead, free-ability, and possibly cache-locality.
A final consideration might be a peculiar feature of C: effective type. A declared array has a fixed effective type and therefore cannot be retyped without violating C's strict aliasing rules but malloc'd memory can be. In other words, you can use a malloc'd block as a backing storage for a generic allocator of your own, but a declared char array cannot be used that way, strictly speaking.

malloc. This is dynamic allocation. You can free or change the size of the allocated memory. Heap is usually much larger than the stack or global variables memory area. The memory has the same storage duration as static objects
The latter cannot be resized or freed (except the automatic objects by exiting the scope). Static and automatic storage is usually smaller than the heap.

Related

what is the main reason of using malloc() in C

I'm currently using C/C++. But what is the main reason of using malloc/new instead of just declare some var on the stack. Like: int a;
Or another example:
int *a; // then use this to track an array
int a = (int)malloc(sizeof(int));
Automatic variables have a lifetime that ends when the program leaves the block of code that declares them. Sometimes you want them to live longer than that; dynamic allocation gives you full control over their lifetime. Sometimes they are too big for the stack; dynamic memory is (typically) less restricted.
With that flexibility comes responsibility: you need to delete them when you've finished with them, but not before. This is difficult to get right if you try to hold onto a raw pointer and do it yourself; so (in C++) learn about RAII, and use ready-made management types like smart pointers and containers to do the work for you.
TL;DR: stack and heap are two different memory areas, they serve different purposes, they have their own access pattern (with everything that implies) and policies (yes, stack memory is way more controlled than heap memory on hw-enforced systems).
Stack memory is a precious, limited resource that needs to be allocated contiguously (you can't chunk it as you would for a heap allocation).
As a consequence of this, its default dimension on many x86 platforms is usually around 1 MB (although this can be increased). Definitely small with regard to how much memory you might allocate with a heap allocation. Your question isn't an exact duplicate of this question but I believe you should take a look at it if you're interested in other reasons for the stack being a limited resource.
Other reasons include visibility scopes (stack stuff is collected/destroyed at the end of the scope while heap allocated memory can be used in other parts of your application until you free it).
The C standard function malloc() with its friends (free(), calloc() and realloc()) allows to dynamically allocate arbitrary large (allowed by OS though) chunks of memory in runtime. This has informal name of dynamic storage duration (formal one from N1570 is allocated storage duration) with following characteristics:
lifetime is cotrolled by malloc() and free() calls. This is unlikely to automatic storage duration variables, where their lifetime is restricted by scope (e.g. block, more precisely by { and }, with exception to VLAs) and static storage duration, which have lifetime of whole execution of program
scope is determined by availability of pointer to allocated data
In other words you use malloc() when you need maximum flexibility of data allocation in runtime. Automatic variables are practically limited by stack size and static variables require compile-time reservation for exact (i.e. static) amount of memory.

C: Malloc and Free

I am trying to undestand the C functions malloc and free. I know this has been discussed a lot on StackOverflow. However, I think I kind of know what these functions do by now. I want to know why to use them. Let's take a look at this piece of code:
int n = 10;
char* array;
array = (char*) malloc(n * sizeof(char));
// Check whether memory could be allocated or not...
// Do whatever with array...
free(array);
array = NULL;
I created a pointer of type char which I called array. Then I used malloc to find a chunk of memory that is currently not used and (10 * sizeof(char)) bytes large. That address I casted to type char pointer before assigning it to my previously created char pointer. Now I can work with my char array. When I am done, I'll use free to free that chunk of memory since it's not being used anymore.
I have one question: Why wouldn't I just do char array[10];? Wikipedia has only one small sentence to give to answer that, and that sentence I unfortunately don't understand:
However, the size of the array is fixed at compile time. If one wishes to allocate a similar array dynamically...
The slide from my university is similarily concise:
It is also possible to allocate memory from the heap.
What is the heap? I know a data structure called heap. :)
However, I've someone could explain to me in which case it makes sense to use malloc and free instead of the regular declaration of a variable, that'd be great. :)
C provides three different possible "storage durations" for objects:
Automatic - local storage that's specific to the invocation of the function it's in. There may be more than one instance of objects created with automatic storage, if a function is called recursively or from multiple threads. Or there may be no instances (if/when the function isn't being called).
Static - storage that exists, in exactly one instance, for the entire duration of the running program.
Allocated (dynamic) - created by malloc, and persists until free is called to free it or the program terminates. Allocated storage is the only type of storage with which you can create arbitrarily large or arbitrarily many objects which you can keep even when functions return. This is what malloc is useful for.
First of all there is no need to cast the malloc
array = malloc(n * sizeof(char));
I have one question: Why wouldn't I just do char array[10];?
What will you do if you don't know how many storage space do you want (Say, if you wanted to have an array of arbitrary size like a stack or linked list for example)?
In this case you have to rely on malloc (in C99 you can use Variable Length Arrays but for small memory size).
The function malloc is used to allocate a certain amount of memory during the execution of a program. The malloc function will request a block of memory from the heap. If the request is granted, the operating system will reserve the requested amount of memory.
When the amount of memory is not needed anymore, you must return it to the operating system by calling the function free.
In simple: you use an array when you know the number of elements the array will need to hold at compile time. you use malloc with pointers when you don't know how many elements the array will need to be at compile time.
For more detail read Heap Management With malloc() and free().
Imagine you want to allocate 1,000 arrays.
If you did not have malloc and free... but needed a declaration in your source for each array, then you'd have to make 1,000 declarations. You'd have to give them all names. (array1, array2, ... array1000).
The idea in general of dynamic memory management is to handle items when the quantity of items is not something you can know in advance at the time you are writing your program.
Regarding your question: Why wouldn't I just do char array[10];?. You can, and most of the time, that will be completely sufficient. However, what if you wanted to do something similar, but much much bigger? Or what if the size of your data needs to change during execution? These are a few of the situations that point to using dynamically allocated memory (calloc() or malloc()).
Understanding a little about how/when the stack and heap are used would be good: When you use malloc() or calloc(), it uses memory from the heap, where automatic/static variables are given memory on the stack, and are freed when you leave the scope of that variable, i.e the function or block it was declared in.
Using malloc and calloc become very useful when the size of the data you need is not known until run-time. When the size is determined, you can easily call one of these to allocate memory onto the heap, then when you are finished, free it with free()
Regarding What is the heap? There is a good discussion on that topic here (slightly different topic, but good discussion)
In response to However, I've someone could explain to me in which case it makes sense to use malloc() and free()...?
In short, If you know what your memory requirements are at build time (before run-time) for a particular variable(s), use static / automatic creation of variables (and corresponding memory usage). If you do not know what size is necessary until run-time, use malloc() or calloc() with a corresponding call to free() (for each use) to create memory. This is of course a rule-of-thumb, and a gross generalization. As you gain experience using memory, you will find scenarios where even when size information is known before run-time, you will choose to dynamically allocate due to some other criteria. (size comes to mind)
If you know in advance that you only require an array of 10 chars, you should just say char array[10]. malloc is useful if you don't know in advance how much storage you need. It is also useful if you need storage that is valid after the current function returns. If you declare array as char array[10], it will be allocated on the stack. This data will not be valid after your function returns. Storage that you obtain from malloc is valid until you call free on it.
Also, there is no need to cast the return value of malloc.
Why to use free after malloc can be understood in the way that it is a good style to free memory as soon as you don't need it. However if you dont free the memory then it would not harm much but only your run time cost will increase.
You may also choose to leave memory unfreed when you exit the program. malloc() uses the heap and the complete heap of a process is freed when the process exits. The only reason why people insist on freeing the memory is to avoid memory leaks.
From here:
Allocation Myth 4: Non-garbage-collected programs should always
deallocate all memory they allocate.
The Truth: Omitted deallocations in frequently executed code cause
growing leaks. They are rarely acceptable. but Programs that retain
most allocated memory until program exit often perform better without
any intervening deallocation. Malloc is much easier to implement if
there is no free.
In most cases, deallocating memory just before program exit is
pointless. The OS will reclaim it anyway. Free will touch and page in
the dead objects; the OS won't.
Consequence: Be careful with "leak detectors" that count allocations.
Some "leaks" are good!
Also the wiki has a good point in Heap base memory allocation:-
The heap method suffers from a few inherent flaws, stemming entirely
from fragmentation. Like any method of memory allocation, the heap
will become fragmented; that is, there will be sections of used and
unused memory in the allocated space on the heap. A good allocator
will attempt to find an unused area of already allocated memory to use
before resorting to expanding the heap. The major problem with this
method is that the heap has only two significant attributes: base, or
the beginning of the heap in virtual memory space; and length, or its
size. The heap requires enough system memory to fill its entire
length, and its base can never change. Thus, any large areas of unused
memory are wasted. The heap can get "stuck" in this position if a
small used segment exists at the end of the heap, which could waste
any magnitude of address space, from a few megabytes to a few hundred.

Mechanism of allocating memory for variable size array

I am not able to understand how variable size array works , whether memory for it is allocated on stack or somewhere else and how information about its size is obtained.
i tried the following code
#include<stdio.h>
int main()
{
int n;
scanf("%d",&n);
int arr[n];
printf("%d\n",sizeof(arr));
return 0;
}
i mean i memory is allocted on stack ,then before running this function the stack frame is to be allocated and memory for local variables has to be allocated ,but the size of array is known after the function calls scanf().
On most contemporary systems with memory protection and so on, you can just grow the stack. If accessing the grown stack causes accesses to memory which is actually outside the valid range of virtual memory for the process, the operating system will catch that and map some more memory your way.
So there's no problem in doing that "on the fly", and of course "allocating n bytes on the stack" is generally about as complex as "stackpointer -= n".
There might be some additional complexity if the function has many exit paths, since they need to unwind the proper amount of stack depending on wether the variable-length array has been allocated or not, not sure how that is generally solved. That would be an easy code-reading exercise to find out.
In C++, this isn't (yet) allowed, although some compilers allow it as a non-standard extension. Dynamically-sized arrays, similar to those in C, are due to be introduced in C++14.
How to implement this is up to the compiler writer, as long as the memory is allocated somewhere and freed automatically. This is typically done by extending the stack frame once the size is known. There may or may not be a check that the stack is large enough, so beware creating large arrays like this.

Difference between static memory allocation and dynamic memory allocation

I would like to know what is the difference between static memory allocation and dynamic memory allocation?
Could you explain this with any example?
This is a standard interview question:
Dynamic memory allocation
Is memory allocated at runtime using calloc(), malloc() and friends. It is sometimes also referred to as 'heap' memory, although it has nothing to do with the heap data-structure ref.
int * a = malloc(sizeof(int));
Heap memory is persistent until free() is called. In other words, you control the lifetime of the variable.
Automatic memory allocation
This is what is commonly known as 'stack' memory, and is allocated when you enter a new scope (usually when a new function is pushed on the call stack). Once you move out of the scope, the values of automatic memory addresses are undefined, and it is an error to access them.
int a = 43;
Note that scope does not necessarily mean function. Scopes can nest within a function, and the variable will be in-scope only within the block in which it was declared. Note also that where this memory is allocated is not specified. (On a sane system it will be on the stack, or registers for optimisation)
Static memory allocation
Is allocated at compile time*, and the lifetime of a variable in static memory is the lifetime of the program.
In C, static memory can be allocated using the static keyword. The scope is the compilation unit only.
Things get more interesting when the extern keyword is considered. When an extern variable is defined the compiler allocates memory for it. When an extern variable is declared, the compiler requires that the variable be defined elsewhere. Failure to declare/define extern variables will cause linking problems, while failure to declare/define static variables will cause compilation problems.
in file scope, the static keyword is optional (outside of a function):
int a = 32;
But not in function scope (inside of a function):
static int a = 32;
Technically, extern and static are two separate classes of variables in C.
extern int a; /* Declaration */
int a; /* Definition */
*Notes on static memory allocation
It's somewhat confusing to say that static memory is allocated at compile time, especially if we start considering that the compilation machine and the host machine might not be the same or might not even be on the same architecture.
It may be better to think that the allocation of static memory is handled by the compiler rather than allocated at compile time.
For example the compiler may create a large data section in the compiled binary and when the program is loaded in memory, the address within the data segment of the program will be used as the location of the allocated memory. This has the marked disadvantage of making the compiled binary very large if uses a lot of static memory. It's possible to write a multi-gigabytes binary generated from less than half a dozen lines of code. Another option is for the compiler to inject initialisation code that will allocate memory in some other way before the program is executed. This code will vary according to the target platform and OS. In practice, modern compilers use heuristics to decide which of these options to use. You can try this out yourself by writing a small C program that allocates a large static array of either 10k, 1m, 10m, 100m, 1G or 10G items. For many compilers, the binary size will keep growing linearly with the size of the array, and past a certain point, it will shrink again as the compiler uses another allocation strategy.
Register Memory
The last memory class are 'register' variables. As expected, register variables should be allocated on a CPU's register, but the decision is actually left to the compiler. You may not turn a register variable into a reference by using address-of.
register int meaning = 42;
printf("%p\n",&meaning); /* this is wrong and will fail at compile time. */
Most modern compilers are smarter than you at picking which variables should be put in registers :)
References:
The libc manual
K&R's The C programming language, Appendix A, Section 4.1, "Storage Class". (PDF)
C11 standard, section 5.1.2, 6.2.2.3
Wikipedia also has good pages on Static Memory allocation, Dynamic Memory Allocation and Automatic memory allocation
The C Dynamic Memory Allocation page on Wikipedia
This Memory Management Reference has more details on the underlying implementations for dynamic allocators.
There are three types of allocation — static, automatic, and dynamic.
Static Allocation means, that the memory for your variables is allocated when the program starts. The size is fixed when the program is created. It applies to global variables, file scope variables, and variables qualified with static defined inside functions.
Automatic memory allocation occurs for (non-static) variables defined inside functions, and is usually stored on the stack (though the C standard doesn't mandate that a stack is used). You do not have to reserve extra memory using them, but on the other hand, have also limited control over the lifetime of this memory. E.g: automatic variables in a function are only there until the function finishes.
void func() {
int i; /* `i` only exists during `func` */
}
Dynamic memory allocation is a bit different. You now control the exact size and the lifetime of these memory locations. If you don't free it, you'll run into memory leaks, which may cause your application to crash, since at some point of time, system cannot allocate more memory.
int* func() {
int* mem = malloc(1024);
return mem;
}
int* mem = func(); /* still accessible */
In the upper example, the allocated memory is still valid and accessible, even though the function terminated. When you are done with the memory, you have to free it:
free(mem);
Static memory allocation: The compiler allocates the required memory space for a declared variable.By using the address of operator,the reserved address is obtained and this address may be assigned to a pointer variable.Since most of the declared variable have static memory,this way of assigning pointer value to a pointer variable is known as static memory allocation. memory is assigned during compilation time.
Dynamic memory allocation: It uses functions such as malloc( ) or calloc( ) to get memory dynamically.If these functions are used to get memory dynamically and the values returned by these functions are assingned to pointer variables, such assignments are known as dynamic memory allocation.memory is assined during run time.
Static Memory Allocation:
Variables get allocated permanently
Allocation is done before program execution
It uses the data structure called stack for implementing static allocation
Less efficient
There is no memory reusability
Dynamic Memory Allocation:
Variables get allocated only if the program unit gets active
Allocation is done during program execution
It uses the data structure called heap for implementing dynamic allocation
More efficient
There is memory reusability . Memory can be freed when not required
Difference between STATIC MEMORY ALLOCATION & DYNAMIC MEMORY ALLOCATION
Memory is allocated before the execution of the program begins
(During Compilation).
Memory is allocated during the execution of the program.
No memory allocation or deallocation actions are performed during Execution.
Memory Bindings are established and destroyed during the Execution.
Variables remain permanently allocated.
Allocated only when program unit is active.
Implemented using stacks and heaps.
Implemented using data segments.
Pointer is needed to accessing variables.
No need of Dynamically allocated pointers.
Faster execution than Dynamic.
Slower execution than static.
More memory Space required.
Less Memory space required.
Static memory allocation is allocated memory before execution pf program during compile time.
Dynamic memory alocation is alocated memory during execution of program at run time.
Static memory allocation. Memory allocated will be in stack.
int a[10];
Dynamic memory allocation. Memory allocated will be in heap.
int *a = malloc(sizeof(int) * 10);
and the latter should be freed since there is no Garbage Collector(GC) in C.
free(a);

why is array size limited when declared at compile time?

for example I can do
int *arr;
arr = (int *)malloc(sizeof(int) * 1048575);
but I cannot do this without the program crashing:
int arr[1048575];
why is this so?
Assuming arr is a local variable, declaring it as an array uses memory from the (relatively limited) stack, while malloc() uses memory from the (comparatively limitless) heap.
If you're allocating these as local variables in functions (which is the only place you could have the pointer declaration immediately followed by a malloc call), then the difference is that malloc will allocate a chunk of memory from the heap and give you its address, while directly doing int arr[1048575]; will attempt to allocate the memory on the stack. The stack has much less space available to it.
The stack is limited in size for two main reasons that I'm aware of:
Traditional imperative programming makes very little use of recursion, so deep recursion (and heavy stack growth) is "probably" a sign of infinite recursion, and hence a bug that's going to kill the process. It's therefore best if it is caught before the process consumes the gigabytes of virtual memory (on a 32 bit architecture) that will cause the process to exhaust its address space (at which point the machine is probably using far more virtual memory than it actually has RAM, and is therefore operating extremely slowly).
Multi-threaded programs need multiple stacks. Therefore, the runtime system needs know that the stack will never grow beyond a certain bound, so it can put another stack after that bound if a new thread is created.
When you declare an array, you are placing it on the stack.
When you call malloc(), the memory is taken from the heap.
The stack is usually more limited compared to the heap, and is usually transient (but it depends on how often you enter and exit the function that this array is declared in.
For such a large (maybe not by today's standards?) memory, it is good practice to malloc it, assuming you want the array to last around for a bit.

Resources