Show Lecture.MemorySegments as a slide show.
CS253 Memory Segments
Mnemosyne, goddess of memory
Segments
There are several “segments”, or areas of memory, where parts
of your program live, in a typical computer architecture:
- Text: executable code (machine instructions)
- Data: initialized static or global data
- BSS: uninitialized static or global data
- Stack: local variables
- Heap: allocated via malloc() or new
Text: executable code
- The text segment contains executable code (cpu instructions).
Don’t obsess over the name—it’s not text strings.
- On today’s computers, text is marked as read-only and executable,
where other segments are not.
- This prevents a berserk program from overwriting
its own instructions via a wild pointer.
- This allows sharing. When several bashes are running, we only need
one copy of bash’s executable code in RAM. This saves memory and
increases the chance of instructions being in cache.
- The text segment is stored in the
a.out
file.
- That’s the executable machine language program on the disk,
called
a.out
(assembler output)
by default by g++.
Data: initialized static data
- The data segment contains initialized static data.
- Globals are implicitly static.
- Local variables can be declared static.
- It is read-write at run-time—programs may alter their variables.
- The data segment is stored in the
a.out
file.
BSS: uninitialized static data
Brain Salad Surgery
- The BSS segment contains “uninitialized” static data.
- It is zero-initialized at initial load of the program.
- It is read-write at run-time—programs may alter their variables.
- BSS has no associated data, so the
a.out
file only has to know how
big the BSS segment is, lay out that much space at run-time, and clear
it. Almost no space required in a.out
.
- Clever compilers put zero-initialized static variables in BSS.
- The origin of the name is unclear—perhaps the assembler pseudo-op
Begin Section started by Symbol.
Stack: local variables
- The stack segment contains local variables
- Declared at function scope or even smaller, e.g., an if block.
- If an initial value is given, it is assigned at run-time.
Otherwise, the value is indeterminate.
Seriously: it’s unknown.
- It contains whatever value the memory had before that.
- It might be initially zero due to the OS clearing memory.
- It is read-write at run-time—programs may alter their local variables.
- It is not stored in the
a.out
at all, except implicitly,
in subroutine preamble code.
Heap: allocated via new
- The heap segment is contains uninitialized dynamic variables.
- It is read-write at run-time—programs may alter their local variables.
- It is not stored in the
a.out
at all.
- Traditionally, free/allocated dynamic memory is kept track of via a
heap data structure,
hence the name.
Example
int b1[3], d1=45;
const int t1 = 299'792'458;
int main() {
static double b2 = 0.0, d2 = 2.718281828;
int s1 = 10, *s2 = new int[s1];
vector<int> s3 = {123,456,789};
map<const void *, string> stuff = {
{&s1, "s1"}, {&t1, "t1"},
{&s2, "s2"}, {&b1, "b1"}, {&d1, "d1"},
{&s3, "s3"}, {&b2, "b2"}, {&d2, "d2"},
{&s2[0], "s2[0]"}, {&s3[0], "s3[0]"},
{&cout, "cout"}, {(void *) exit, "exit"},
};
for (auto [addr, name] : stuff)
cout << setw(14) << addr << ' ' << name << '\n';
delete[] s2;
}
0x401b50 exit
0x4051c8 t1
0x608118 d1
0x608120 d2
0x608140 cout
0x608258 b1
0x608268 b2
0xdc92b0 s2[0]
0xdc92e0 s3[0]
0x7ffd4fab5f30 s3
0x7ffd4fab5f50 s2
0x7ffd4fab5f58 s1
What is in each memory segment?
Summary
Text | Data | BSS | Stack | Heap |
instruction/const | initialized global | uninitialized global | local var | dynamic memory |
allocated at compile-time | allocated at run-time |
read-only | read-write |
occupies space in a.out | no space in a.out |