So apparently dynamic memory allocation allows memory to be allocated during runtime instead of compile time like static memory allocation. I also understand that using these functions in malloc.h we can save memory by unassigning memory blocks which are not in use by using free(). But my confusion lies in whether the following code comes under dynamic memory allocation or not.
#include <stdio.h>
int main() {
int n;
scanf("%d",&n);
int a[n];
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
for(int i=0;i<n;i++){
printf("%d",a[i]);
}
return 0;
}
How is malloc.h functions beneficial in a case where I want the user to specify the size when the above code serves the purpose of allocating during runtime? How are malloc, calloc and realloc different from each other? Also, what if malloc is being used as follows: (after initialising ptr)
ptr=(int*)malloc(3*sizeof(int));
How is this different from
int ptr[3];
If the memory required is unknown during writing of the code, can I not declare a pointer and then simply do a ++ to store value in the next memory address as follows?
int* ptr;
while(1){
scanf("%d",ptr);
ptr++;
}
But my confusion lies in whether the following code comes under dynamic memory allocation or not.
No, that code does not use “allocated” memory as the C standard specifies it. (Memory for objects is always allocated in one way or another, so this term of the C standard is imprecise. What the C standard calls “allocated” memory is better called “dynamically allocated.”)
Also, what if malloc is being used as follows:
ptr=(int*)malloc(3*sizeof(int));
How is this different fromint ptr[5];
Well, first, 3
is different from 5
.
Second, int ptr[5]
inside a function is usually allocated on the hardware stack, and hardware stack space is somewhat limited. We could make stack space very large, and there are mechanisms to request that for your program, but it is kept limited for various reasons, one of which is so that a “runaway” program will be caught before it consumes an inordinate amount of stack space.
Further, with your example using int a[n];
, there is no method to detect the user has entered an n
that is too large for your hardware stack, other than trying it and having your program crash as a result.
Another major difference is in the lifetime of the objects. For int ptr[5]
, the memory will be automatically released when the function ends execution. This form of allocating memory cannot be used to return memory to a calling routine. For example, if you have a complicated routine that benefits from having some results of initial calculations stored in a data structure for later use, you cannot allocate the memory for that with int ptr[5]
or similar declaration and then return it to the calling routine. With int *p = malloc(5 * sizeof *p);
, you can return the memory address to the calling routine, and the memory will remain allocated when your function ends execution.
If the memory required is unknown during writing of the code, can I not declare a pointer and then simply do a ++ to store value in the next memory address as follows?
int* ptr; while(1){ scanf("%d",ptr); ptr++; }
No. First, you did not set ptr
to any value, so you do not know where it points. Second, if you did set ptr
to some address where there was memory available for storing values, you can safely store only as many values as there is memory reserved for. There are multiple things inside your program using memory for different things: The standard input and output streams have buffers. printf
has its own workspace. malloc
has data structures recording what memory is in use. You cannot just assume you can take some memory address and keeping writing to that address and beyond without running into something else in your process. At some point, in common systems, you will overwrite other data that your program needs or you will run into the end of memory mapped for your process, and a segmentation fault will occur.
How are malloc, calloc and realloc different from each other?
Each of them tries to find available space in your process’ address space, updates the memory management system’s records about which addresses are available for allocation, and returns a pointer to the space allocated for you (or returns a null pointer if space was not available). They also ask the operating system to map more memory into the address space, if needed.
malloc
merely provides you the address without making any assurances about what is in that memory.
calloc
provides you the address while assuring that the contents of memory was set to zeros.
realloc
takes an address of an old memory allocation and provides new space (possibly starting at the same location as the old space). It assures that the contents of the new memory contains a copy of the contents of the old memory, up to the shorter of the two. It provides no assurance about the contents of memory beyond that. (If you pass realloc
a null pointer, it attempts to make a new allocation, behaving the same as malloc
.)