Every Linux (and Unix) program has different memory areas. They are stored in separate parts of the executable program's disk file. Some of the sections are loaded into the same part of memory when the program is run. All running copies of the same program share the executable code (the text segment). The size program shows the sizes of the different areas for relocatable object files and fully linked executable files.
The address space of a running program may have holes in it, and the size of the address space can change as memory is allocated and released. On modern systems, address 0 is not part of the address space, so don't attempt to dereference NULL pointers.
At the C level, memory is allocated or reallocated with one of malloc(), calloc(), or realloc(). Memory is freed with free(). (Although realloc() can do everything, using it that way isn't recommended). It is unusual for freed memory to be removed from the address space; instead, it is reused for later allocations.
Extreme care must be taken to
Free only memory received from the allocation routines,
Free such memory once and only once,
Free unused memory, and
Not "leak" any dynamically allocated memory.
POSIX provides the strdup() function as a convenience, and GLIBC provides getline() and getdelim() for reading arbitrary-length lines.
The low-level system call interface functions, brk() and sbrk(), provide direct but primitive access to memory allocation and deallocation. Unless you are writing your own storage allocator, you should not use them.
The alloca() function for allocating memory on the stack exists, but is not recommended. Like being able to recognize poison ivy, you should know it only so that you'll know to avoid it.