0% found this document useful (0 votes)
3 views

2-types-address-memalloc-web

The document covers the interaction between user-level processes and the operating system, emphasizing system calls and memory management. It introduces data types in C++, detailing primitive types and their operations, as well as the organization of memory space for processes. Additionally, it discusses dynamic memory allocation and the concept of the heap in programming.

Uploaded by

cranckcracker123
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views

2-types-address-memalloc-web

The document covers the interaction between user-level processes and the operating system, emphasizing system calls and memory management. It introduces data types in C++, detailing primitive types and their operations, as well as the organization of memory space for processes. Additionally, it discusses dynamic memory allocation and the concept of the heap in programming.

Uploaded by

cranckcracker123
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 21

Types and

Memory, Part I
CS 61: Lecture 2
9/11/2023
Recap of Lecture 1
• User-level processes interact with each other
and the hardware via the operating system—
in particular, via system calls
User- User- User-
//Process X wants to read 32 bytes of data level level level
//from a file that is stored on the SSD. process process process
X Y Z
//First, get a file descriptor that allows
//the process to interact with the file.
int fd = open(“file.txt”, O_RDONLY); Operating
system
(Kernel-level code)
MMU MMU MMU MMU

Hardware

RAM SSD UX Network


Recap of Lecture 1
• User-level processes interact with each other
and the hardware via the operating system—
in particular, via system calls
User- User- User-
//Process X wants to read 32 bytes of data level level level
//from a file that is stored on the SSD. process process process
X Y Z
//First, get a file descriptor that allows
//the process to interact with the file.
int fd = open(“file.txt”, O_RDONLY); Operating
//Declare an array to hold the file data.
system
char buf[32]; (Kernel-level code)
MMU MMU MMU MMU
//Read the file data into the array!
ssize_t bytes_read = read(fd, buf, sizeof(buf)); Hardware

RAM SSD UX Network


Recap of Lecture 1
• User-level processes interact with each other
and the hardware via the operating system—in
particular, via system calls
User- User- User-
• A process contains in-memory state like: level level level
• Program variables (e.g., global variables and local process process process
variables) X Y Z
• Function code
• At any given moment, a particular CPU
executes code from a single entity (either a Operating
user-level process or the OS) system
• The OS leverages various hardware features to (Kernel-level code)
maintain order on the computer MMU MMU MMU MMU

• MMU (memory management unit): OS configures it


so that, when a process executes, it can only touch Hardware
the memory belonging to that process
• Timer hardware: Ensures that the OS will eventually
get to run even if a process loops forever RAM SSD UX Network
Recap of Lecture 1
• User-level processes interact with each other
and the hardware via the operating system—in
Use Kerne Use Kerne Use
particular, via system calls r l r l r

interrup
schedul

schedul
• A process contains in-memory state like:

timer
sysca
(1) (2) (3) (4)

e
ll

e
t
• Program variables (e.g., global variables and local
variables)
• Function code
Flow of time from the
• At any given moment, a particular CPU perspective of the leftmost
executes code from a single entity (either a CPU
user-level process or the OS)
• The OS leverages various hardware features to
maintain order on the computer MMU MMU MMU MMU

• MMU (memory management unit): OS configures it


so that, when a process executes, it can only touch Hardware
the memory belonging to that process
• Timer hardware: Ensures that the OS will eventually
get to run even if a process loops forever RAM SSD UX Network
Today’s Lecture: Data Types and Memory
• In a C++ program:
• What types of data values can
User- User- User-
be stored in memory? level level level
• For each type, what kinds of process
X
process
Y
process
Z
operations does C++
support?
Operating
• How is the memory space of system
(Kernel-level code)
a process organized? MMU MMU MMU MMU
• Where does code live?
• Where does data live, and
Hardware
how long does it live?
RAM SSD UX Network
Primitive Types in C++
• A type describes two things
• A set of possible values
• A set of allowable operations on those values
• A primitive type is one that is not composed of other types
• Different programming languages define different primitive types!
• In C++, there are primitive types for:
• Integers (e.g., 57, -9123, 0, with arithmetic, comparison, and bitwise
operations)
• Floating-point numbers (e.g., 61.925, INFINITY, NAN, with arithmetic and
Arithmetic:
comparison operations)+, -, *, /, %
• Booleans (i.e., true, false, with comparison operations (==, !=))
Comparison: <, <=, ==, >=, >,!=
• Pointers (i.e., the memory locations of other
values,Bitwise:
with limited~,arithmetic
&, |, ^, operations
<<, >>
(addition, subtraction, comparison))
Primitive Types in C++
• A type describes two things
• A set of possible values
• A set of allowable operations on those values
• A primitive type is one that is not composed of other types
• Different programming languages define different primitive types!
• In C++, there are primitive types for:
• Integers (e.g., 57, -9123, 0, with arithmetic, comparison, and bitwise
operations)
• Floating-point numbers (e.g., 61.925, INFINITY, NAN, with arithmetic and
comparison operations)
• Booleans (i.e., true, false, with comparison operations (==, !=))
• Pointers (i.e., the memory locations of other
values, with limited arithmetic operations int id = 999;
(addition, subtraction, comparison)) int* ptr = &id; //ptr contains the
//memory address
//of the variable id
Values in C++
• CPU instructions manipulate bits (zeroes and
ones) thatA are stored in
(simplified!) registers
view and memory
RAM
of an x86
• 8 bits is called a byteCPU and Byte N-
RAM
Register 1
• An “x-bit”%rax
CPU has
s registers
%rbx
that are x bits in size,

...
e.g., a 64-bit
%rcx
Intel CPU%rdx has registers that are 64 bits
(i.e., 8 bytes) large
CPU

RAM
controll
er
ALU
Instructi
on ALU ALU
op output
decode
Byte 0
RAM controller command
Values in C++
• CPU instructions manipulate bits (zeroes and
ones) that are stored in registers and memory
• 8 bits is called a byte
• An “x-bit” CPU has registers that are x bits in size,
e.g., a 64-bit Intel CPU has registers that are 64 bits
(i.e., 8 bytes) large
• A bitConsider
pattern can
this be(i.e.,
16-bit represented in .various
2 byte) pattern . ways
.
Raw bits: 01100111’11000011
Hex: 67C3
Decimal: 26563

the apostrophe does not exist in the actual binary


representation
Values in C++
• Recall that:
• C++ programs execute on an abstract machine which
defines stuff like:
• A memory model
• Valid data types
• Control flow operations (e.g., if-else)
• The compiler translates a program’s manipulation
of the abstract machine to actual CPU
instructions that can execute on real hardware
• The C++ standard defines minimum sizes for
integer data types, but allows a compiler to
represent them using more bits (as
Values in C++
Values in C++
• Different types have //On x86-64, all of these
different rules for //values have the same size
//and the same bit-level
interpreting the bits in a //representation!
value int a1 = 1;
• So, the same set of bits unsigned char a2[] = {1,0,0,0};
unsigned short a3[] = {1,0};
mean different things unsigned a4 = 1;
when interpreted as float a5 = 1.4013e-45;
different types!
• This means that you
cannot tell the type of
a value just by looking
The sizeof() operator in C++
• The C++ operator sizeof(x) allows a program to retrieve
the size in bytes of the value belonging to x (as defined
by x’s type)
• Ex: int x = 42; printf(“%d\n”, sizeof(x));
• Ex: printf(“%d\n”, sizeof(int)); //i.e., you can also
//pass a type name to sizeof()
• For example, on a Linux x86-64 machine:
sizeof(char): 1 sizeof(unsigned char): 1
sizeof(short): 2 sizeof(unsighed short): 2
sizeof(int): 4 sizeof(unsigned int): 4
sizeof(long): 8 sizeof(unsigned long): 8
sizeof(float): 4
sizeof(double): 8
Objects in C++
• An object is a value stored in one or Logical Actual
more adjacent memory locations view of physical
• Values like 42 or false are Platonic: they memory
Byte N-1 RAM
exist in the spirit world and can never change
• However, an object might contain different
values over time

...
We’ll talk
int x = 0; //x is an object living
about the
//somewhere in memory;
mapping in a
//the object’s current
few weeks!
//value is 0.
x = 42; //The memory location
//belonging to object x
//now stores the value 42. Stores the
binary
• A computer uses RAM (“random access 4
representation
memory”) hardware to store objects 2 0
of the value
• A modern laptop or desktop has ~8GB—32GB
of RAM
• An iPhone 14 has 6GB of RAM
Byte 0
• A datacenter server has ~16GB—1TB of RAM
(5) Via the terminal shell
Lifecycle or a graphical interface,
the user requests the > bsort in.txt

of a launching of a new
instance of the
Process executable
SSD
(6) The shell or GUI
//Pseudocode to sort an array uses system calls to:
//of length n. (4) The binary (“executable”) • Create a new process
bubblesort(arr, n): arrives on a user’s storage • Read the code and
for(i=0; i<(n-1); i++):
for(j=0; j<(n-i-1); j++): device (e.g., via an Internet static data from the
if(arr[j] > arr[j+1]): download, a USB stick, or a on-disk executable;
tmp = arr[j]; local compilation) place that
arr[j] = arr[j+1];
arr[j+1] = tmp;
information into the
memory region that
(1) Design belongs to the new
the process
program • Have the new
process start running
.cc the loaded code!

(2) Translate
.hh (3) Compile
design to the program
//C++ variables declared outside of
//a function are globals (i.e.,
//visible to any function). They
//have a static duration---they
//are created when the program Address
//launches and destroyed when the
//program exits.
space
Stores info
int g = 42; //Initial value is 42. about active Byte N-1
functions Stack
void increment(bool do_print) { (e.g., the
bool is_even; //This variable is a values of
//local variable: it’s created local
//when the enclosing function variables)
//starts, is only visible to
//that function, and dies when
//the function returns.

g++;
is_even = ((g % 2)==0); Pulled
if (do_print) { from
printf(“%d\t”, g); executable
printf(“even: %s\n”, into RAM

}
is_even ? “true”: “false”); during (6) Static data
}

int main() { Code


increment(true); //Prints “43 false”
increment(true); //Prints “44 true” Byte 0
return 0; SSD
}
OK . . . but
what if you
can’t predict
how many
variables your
program will
need?
• Ex: Your audio mixing
program cannot
predict how long a
new track will be
• Ex: Your ML program
reads training data
from a live stream and
you don’t know the
stream length a priori
Dynamic memory allocation to the rescue!
• Instead of determining how many
variables you need at program
development time . . .
void f() {
int x, y; //f always gets
//two ints
• . . . allocate the needed amount of
memory at program execution
time:
void f() {
int n = read_int_from_user();
int* data = new int[n];

But where for (int i = 0; i < n; i++) {


does this do_stuff(data[i]);
data live in
the address
space?
The Heap
• Dynamically-allocated memory lives in Address
a program region known as the heap space
Byte N-1
• A programmer must explicitly Stack
allocate and deallocate heap memory
int* ptr = new int; //Allocation;
//the new int
//lives here
do_stuff(ptr);
delete ptr; //Deallocation
Pulled
• In contrast: from Heap
• The compiler and program loader executable
into RAM
automatically allocate memory space during (6) Static data
for static data
• The compiler automatically emits
machine instructions to allocate and Code
deallocate memory space for stack Byte 0
variables—we’ll see this in a few lectures! SSD
Real-life Example of an
Address Space Address
space
#include <cstdio> Byte N-1
int main(){ Stack
int x = 42; //Local variable in function
int* ptr = new int[64]; //ptr is a local variable
//whose value is the address
//(i.e., starting memory
//location) of the array
//of ints in the heap

printf(“&x: %p\n”, &x); //0x0000’7ffd’d608’f94c Heap


printf(“&ptr: %p\n”, &ptr); //0x0000’7ffd’d608’f940
printf(“ptr: %p\n”, ptr); //0x0000’0000’0185’22b0 Static data
printf(“main: %p\n”, main); //0x0000’0000’0040’1136

return 0; Code
} Byte 0

You might also like