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);
Related
I just wanted to know if declaring a variable as mentioned above is a system call to the Kernel?Because I have read that Kernel is only responsible when memory is being allocated dynamically if it is not a system call then how memory gets allocated for it,is os responsible for this memory allocation?
is a system call to the Kernel?
No. There is no call to the kernel.
If your variable has static storage duration, the memory for it will be allocated by the OS during the program load. The size of the area where static storage duration objects are located is known build time.
If it has automatic storage duration it will be allocated in most modern implementations on the stack during the program execution.
But both variables can be optimized out by the compiler if they are not needed to produce the required observable program behaviour.
If they are optimized out - no memory will be allocated for them.
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.
I'm learning C now and trying to figure out how the memory management of C works. Please correct me if I am wrong, but as I know for:
Static memory allocation - this happens during compile time. The compiler allocates the necessary memory needed for static memory.
Static memory deallocation - the memory is deallocated automatically when the block/function is finished running (for local variables) or when the entire program has finished executing (for global variables).
Dynamic memory allocation - the memory is allocated during run-time because the size of the input is unknown at this time.
Dynamics memory deallocation - the memory is deallocated when the free() is executed.
Is this about right? Am I missing anything?
There are 3 different kinds of storage duration in C language:
static: the lifetime of the variable is the lifetime of the program. It is allocated at load time (only defined at compile time) and only freed when the operation system unloads the program. Static variables are variables declared outside any functions, and local variables (declared in a function or block) having the static modifier
automatic: automatic variables are declared inside a block (or function), with no storage modifier. Their lifetime starts at the beginning of the bloc and ends at the end of the bloc. They are generally allocated at the beginning of the bloc and deallocated at its end, but because of the as if rule, optimizing compilers could allocate them sooner and free them later, for example if the bloc in located inside a loop.
dynamic: they are allocated manually through malloc, and will only be deallocated by free
Common implementations use a system stack for automatic variables and a memory pool (asking the Operating System when more memory is needed) for dynamic ones, but this is an implementation details
When multithreading is used, a fourth kind of storage duration is available: thread storage duration. Those variable are declared with the _Thread_local storage class modifier. Their lifetime is the duration of the thread, and each thread has its own copy of them.
For common implementation, they are managed the same as static variables: they are allocated by the operating system when the thread is created, and reclaimed (still by OS) when the thread ends.
Some remarks regarding your wordings:
Static memory allocation - this happens during compile time.
Beware, compile time and load time are different. At build time only a file is created, and memory is only allocated by the system at run time
Static memory deallocation - the memory is deallocated automatically when the block/function is finished running (for local variables)...
There is a confusion between scope (local vs. global) and storage duration. A function can contain static variables, that is one of the reasons for the static keyword
Dynamic memory allocation - the memory is allocated during run-time because the size of the input is unknown at this time
This is one possible reason for the programmer to use dynamic memory, but there might be others, for example because the code would be cleaner that way. In particular, dynamic memory is a nice tool when you want to mimic Object Oriented Programming in C language.
I think most of the words you say is correct. Just a few points I wanted to add.
For global and static variables, if they are initialized, their values are present in the resulting binary so yes, static memory allocation (actually it is not memory but anyways) happens in compile time but consider uninitialized global variables (bss section). only their length is written in the resulting binary image because writing thousands of zeros to the compiled image would be silly. in this case memory allocation is handled by loader at load time. it allocates required space, maps them to virtual addresses of your variables and zero out the memory.
And free is not necessarily meaning that you give the unused memory to the operating system. Usually the c standard library keeps track of free'd chunks, and concatenates them if it can in order to not execute a sbrk or equivalent system call next time you want to malloc because they are relatively costly. It is I believe highly dependent to the library implementation
I am working on learning c. I understand that malloc() allocates a block of bytes that cannot be changed or corrupted without user request, however I find myself using it very often. To be exact, I am using malloc every time that I want to create either a struct or any of its contents that I want to reference in the future. I also do understand to free() the allocated memory when its complete.
Is my use of malloc correct?
Dynamic memory allocation (malloc and family) are there for two reasons:
Your data needs to persist beyond the scope that allocated it (e.g. multithreading)
Whatever you are allocating is too large for your stack
You should really be avoiding to allocate dynamic memory for any other reason. Automatic (stack) variables are far less prone to errors and are automatically deallocated for you at the end of the scope.
Having "corrupted memory" like you call it can only really arise from bad programming and can happen on both the stack and the heap and you should not rely on dynamic memory to provide safety from buffer overflows or other mistakes that lead to memory corruption.
There is a reason why many functions in the C standard library get a pointer to a buffer as an argument to put results in: it allows you to allocate those buffers on your stack. e.g:
ssize_t read(int fd, void *buf, size_t count);
Also as mentioned by another answer: Your stack memory is already in the CPU cache and is thus far faster accessible.
Please also consider the other types of allocation:
int foo;
outside of a block will allocate a global variable, which is alive during the whole lifetime of your process, and visible for other modules of the program.
static int foo;
outside of a block is the same but visible in the actual module only.
int foo;
inside a block is alive only while the code in the block runs, then it's destroyed.
static int foo;
inside a block is visible in the block only, but it preserves its value for the entire lifetime of the process.
I'm doing a lot of embedded C coding, and using malloc() is absolutely prohibited. And it's entirely possible. You typically need malloc() if you don't know the size of your problem at compile time. But even in some cases like that, you can replace dynamic memory allocation with other techinques like recursion, line-based processing etc, etc.
It depends on what you mean by
cannot be changed or corrupted without user request
If you are referring to code - then it's usually called client, not user. And it's still unclear what do you mean by that. But that's not the point.
The point is that malloc() is one of the functions used for dynamic memory allocation. It means that you can pass an address returned by this function somewhere else and data stored there will be there until it's manually deallocated. Unlike static memory allocation which is automatically freed when it's out of the scope.
So, you probably shouldn't be using malloc() if memory allocated by it is freed in the same scope, just because it's meaningless and because static allocation is faster because it's easier for CPU to cache and it's initialized at program startup, not at runtime as heap allocated memory.
I have a question to ask, which occurred when reading the concept of static variables. If I create an allocated block of memory in a function, using malloc, and then the function returns to main, without having used free() on the allocated memory, will that memory block be susceptible to changes in the course of the program, or not? I mean, after I leave the function is it possible that the memory block can be overwritten by another process, while I wanted to use it and/or edit it in my way, or is it "locked" from something like that, until I free it? Is it possible for the block to be considered as free of data before I free it?
Once you malloced a certain num ber of bytes, it's going to be alive throughout your program's lifetime unless you explicitly free it.
It doesn't matter in which function you did the malloc, the memory is going to be alive for you to use anywhere in your program provided you have a valid pointer to the malloced memory.
The C Standard specifies a storage duration called allocated (in C99 6.2.4 Storage duration of objects.) The lifetime of allocated storage is from allocation (with malloc, calloc, realloc) until deallocated (with free or realloc). So, yes, returning from a function does not invalidate allocated storage (unlike automatic storage like local variables). You can expect it to be still allocated. And you can read and write it as long as you have a valid pointer to such storage.
When memory is allocated with malloc, it stays allocated to your program as long as your program is running and as long as you do not free this memory block. So this memory block cannot be modified or overwritten by another process.
Generally, the malloced memory block cannot be overwritten by another process because the two processes reside in two different virtual address spaces, unless you share the memory block with another process in some way like this.
OK, so I think you're asking what happens in a situation like this...
#include <stdlib.h>
void myfunc( void )
{
static void* p = malloc(BLOCK_SIZE);
// perhaps the rest of this function uses the pointer to the allocated mem...
}
int main( int argc, char** argv )
{
myfunc();
// the rest of the program goes here...
}
... and asking if "the rest of the program" code could write into the memory block allocated by myfunc().
The heap would still have the memory allocated, as it doesn't know that only the code in myfunc() holds a pointer to the memory block. But it won't 'lock' it either (i.e. protect it from being written to -- there is no such concept in the C language itself.)
Due to the heap still regarding the memory block as already allocated no code that used a subsequent malloc() would get a pointer to a block that is within the one you already allocated. And no code outside of myfunc() would know the the value of the pointer p. Thus the only way any later code could end up writing to the block is 'accidentally' by somehow gaining a pointer to a location that happened to be within the memory in your block (probably due to some sort of code bug), and writing to it.