So memory segmentation can be done with or without paging. I always hear people talking about stack and heaps when discussing something memory related in C++. However, what I do not get is that if the program's memory (its virtual address space) is segmented using pages, it won't get divided into stack, heap, etc., right? But rather it is divided into pages without names – in that case (with the assumption that my understanding of segmentation is correct), can you still talk about the stack and heap?
Also, if the virtual address space is divided into pages, where does the stack, heap, data, etc. segments come from?
Best Answer
The stack and heap in C/C++ describe different mechanisms of memory allocation. They can also be called “automatic storage” and “free store”. If you allocate data on the free store/heap, you are responsible for managing the lifetime (calling
delete
orfree()
). This is mostly unrelated to memory pages.Memory pages are a block of virtual addresses. The virtual address space of a process is created by the operating system by mapping pages into the address space.
A process uses different areas of the address space differently. One area will be the stack. Other areas will hold the contents of executable files and libraries. These files may have different segments, e.g. for executable code, for constants, and space for variables.
Here I've pulled the address space mappings of a Perl interpreter using pmap:
Note that the smallest size is 4K, that is the page size on my system.
We can see on the rightmost column which files (executables or libraries) were mapped into the address space at which offset. There are also a couple of special regions, such as
[stack]
. Some of the anonymous regions can be used as a free store/heap. There may be gaps between the mapped ranges of the address space. Trying to access memory in an unmapped range will cause a segfault.Each of those regions consists of one or more pages. This is important, because pages can have access protections: the executables and libraries provide executable pages for code, read-only pages for constants, and read-write pages for variables. This is a security mechanism to avoid arbitrary data from being executed (though this doesn't matter very much for an interpreter). The pages for the heap and stack will be readable and writeable, but not executable.
An address range may be mapped, but the page for that address might not exist at the moment. Using such an address will trigger a page fault. The operating system can intercept the page fault and add the page. For example, not all pages of the 136K for the stack may exist when the process starts. Instead, the pages are added on demand. Or, a page may have been swapped out to disk. A page fault will cause that page to be loaded back into physical memory.