How is space from malloc allocated?

Whenever we load a process (which consists of object code, static and global variables, stack and heap space) into main memory it would be of fixed size. But, the program doesn't know in advance how much heap memory is it gonna need? Is there some fixed stack and heap space given to each process of some size in advance? But, then wouldn't it be a waste of space to give same amount of stack and heap space for each process ?

There can be other possibility that whenever we execute malloc, operating system gives us free space (basically holes) from main memory which is not the part of process. So, process size can increase at runtime. Then, Why is stack and heap space given to a process in the first place?

There are many techniques that can be used by an OS. Still, usually when the OS loads an executable file, it finds inside it how much memory to allocate at the beginning for the "heap".

The "stack" can be set to a minimum amount, and then gradually increased as soon as things are pushed on it.

When the program starts, it will ask for more heap memory using system calls, and the OS will allocate the required physical memory (if available, of course), and map it to the process address space. If the OS uses virtual memory, some of the allocated memory can also be swapped to disk if there's need for that.

Why is stack and heap space given to a process in the first place?

Usually, that's a small amount, which is needed to perform basic program startup. For instance, suppose that your program was written in C, using a few global variables. In principle, the space for these globals could be allocated on the heap after the program starts, but that's cumbersome to handle. Instead, if the OS preallocates a small amount of memory, that can be used for globals -- those are never going to be deallocated anyway. Even better, doing so can ensure that globals have a fixed address, so the compiler can access then using their known address. Allocating them on the heap after the program starts may (depending on the OS) instead allocate them at unpredictable addresses, possibly requiring an indirection to access them.

malloc is a library function that makes use the sbrk system call. The manual page of malloc on Linux says:

Normally, malloc() allocates memory from the heap, and adjusts the size of the heap as required, using sbrk(2).

If we now look at sbrk manual page:

   brk() and sbrk() change the location of the  program  break,
which  defines  the end of the process's data segment (i.e.,
the program break is the first location after the end of the
uninitialized  data  segment).  Increasing the program break
has the effect of allocating memory to the process; decreas
ing the break deallocates memory.