Valgrind can also find the use of invalid heap memory using the memcheck tool. For instance, if you allocate an array with malloc or new and then try to access a location past the end of the array: char.x = malloc (10); x 10 = 'a'; Valgrind will detect it. For instance, running the following program, example2, through Valgrind.
The syntax of malloc is (void*)malloc(size_t size). So the syntax says that malloc requires a size, it will return the pointer basically a void pointer and size t is defined in <stdlib.h> as an unsigned integer. Malloc function simply allocates a memory block according to the size specified in the heap as you can see in the syntax that size needs to be specified and, on the success, it returns a pointer pointing to the first byte of the allocated memory else returns NULL. So, the job of malloc is to allocate memory on run time.
Malloc doesn’t have an idea of what it is pointing to; it simply means it doesn’t know what data will store in that memory location. It merely allocates memory requested by the user without knowing the type of data to be stored inside the memory. That’s why it is returning a void pointer.
Malloc just allocates memory after that it is the user’s responsibility to typecast to an appropriate type so that it can be used properly in the program. Void pointer is a pointer which can point any type of data malloc returns void pointer because it doesn’t know which type of data will get stored inside that memory.
Here we are asking malloc to allocate 6 bytes of memory now if it a success malloc will return a void pointer. In that case, we have to typecast it to an integer type pointer because we want to store an integer in that memory. Here malloc allocates 6 bytes of memory in a heap, and the address of the first byte is stored in the pointer ptr.
Here is a simple example program in order to understand the concept of malloc in a proper way.
Here you can see with the printf function I am asking the user to enter the number of integers. We have declared two variables above i and n. Variable n is the place where we will store the number entered by the user. After that, we have malloc function; we want the malloc to allocate the sizing equivalent to the size of n integers. We are multiplying size if int with n; this will give us the size of n integers. After that, malloc will return a void pointer, and we are typecasting it to an integer pointer, and we are storing the address within the ptr pointer. Typecasting is important as it is a good practice.
Now, if the pointer contains NULL, it means the memory is not available. So we will simply exit out of the program with the exit failure status. If this is not the case, we can easily run the for a loop.
The loop will run from 0 to n-1, and we will ask the user to enter integer one by one every time. Within the scanf function, there is one thing written ptr+i as we know that ptr contains the address of the first byte of memory. Let’s say that address is 1000 here i is equal to zero initially so 1000+0 is 1000 so within that address our first integer will be stored then after that when i becomes 1 so 1000+1 which has internally interpreted as (1000) +1*4 if I am assuming the size of the integer is 4 bytes, and it would be equal to 1004, so the next integer will be stored within 1004 location. And this will continue in this way the addresses are like 1000, 1004, 1008 and so on. We are not using ampersand before ptr+i because ptr is already giving us the address when we write ptr, which is simply a pointer, and it contains the address, not the value, so there is no requirement of putting ampersand before it, and this concept should be clear.
Here in this loop, we are simply doing one thing we are printing all the integers on the screen; obviously, we are using ptr+i, but here, in this case, we are dereferencing it because ptr+i represents an address, so we need to dereference it. If i equal to 0, it will be 1000 because we are assuming the first address will be 1000, so we are dereferencing it; we will get the first integer then i equal to 1, and it will become 1001 but interpreted as 1004 if the size of the integer is 4. Again. We are dereferencing it, so it will give us the 2nd integer. In this way, everything works.
So, this is basically a simple program which is asking users to enter n integer, and then we are simply displaying those integers on screen. After executing the program, this will display.
First, we are asking the user to enter the number of integers, and then the user is entering the integers, and we are simply displaying them on the screen.
There is nothing wrong in the above program as long as we are continuing it for a very long time here we are borrowing memory from the heap, but we are never returning the memory back to heap it only happens in that case where program/application have to run for a long duration like 24 hrs. They will be calling malloc function again, and again that means every time they are borrowing memory from the heap and never returning, this is bad programming, so we should write free (the address of memory which should be released) before returning. So whenever using malloc free is important. So, using malloc, we have conserved memory, and malloc does allocate memory as big as you ask it.
Happy dynamically memory allocation!