<<

C’s memory model LAST TODAY NEXT

• Transition to • C’s Memory Model Numbers in C

• Code organization • Arrays and pointers

• Contracts • Pointer casting

• Compiling • Arrays on the stack

• Memory management • Structs on the stack • “Address of” operator • Undefined behavior Transition to C

LOST GAINED

Contracts Preprocessor

Explicit memory management Safety

Garbage collection Tools: valgrind

Memory initialization

Tools: Interpreter (coin) Memory model

OS restricted H 0xB4B main H 0xB4B hdict_lookup Local STACK k 0x73C i 0 memory k1 0x73C key_equiv k2 0x735

2 4 Allocated HEAP memory 0x735 0x73C 73 42 "hamlet" read-only TEXT "rose" main … hdict_lookup … CODE key_hash … read-only key_equiv … OS restricted Exercise

int *x = xmalloc(sizeof(int)); *x = 3; int *y = x; *x = 4; printf("%d\n", *y);

What is printed after executing this code? Allocating an array

int *A = xmalloc(sizeof(int)*5);

A 0xBB0 0xBB4 0xBB8 0xBBC 0xBC0 … … A[0] A[1] A[2] A[3] A[4] Allocating an array

int *A = xmalloc(sizeof(int)*5); A[1] = 7; A[2] = A[1] + 5; A[4] = 1

A 0xBB0 0xBB4 0xBB8 0xBBC 0xBC0

… 7 12 1 … A[0] A[1] A[2] A[3] A[4] Allocating an array

int *A = xmalloc(sizeof(int)*5); A[1] = 7; A[2] = A[1] + 5; A[4] = 1 *A = 42;

A 0xBB0 0xBB4 0xBB8 0xBBC 0xBC0

… 42 7 12 1 … A[0] A[1] A[2] A[3] A[4] Allocating an array

int *A = xmalloc(sizeof(int)*5); A[1] = 7; A[2] = A[1] + 5; A[4] = 1 *A = 42;

• A is the address of the first element of the array. • A+1 is the address of the next element. • A+i is the address of ithelement of A. • In fact, A[i] is convenient syntax for *(A+i)

i is not bytes but the number of elements to skip over. Pointer arithmetic

void print_memory_int(int* start_ptr, int num) { int *ptr = start_ptr; for (int i = 0; i < num; i++) { printf("%d\n", *ptr); ptr = ptr + 1; } } Example: print elements in an allocated array

void print_memory_int(int* start_ptr, int num) { int *ptr = start_ptr; for (int i = 0; i < num; i++) { printf("%d\n", *ptr); ptr = ptr + 1; } }

int *A = xmalloc(sizeof(int)*5); print_memory_int(A,5); xmalloc does not initialize memory!

KAYNAR3:code dilsun$ ./a.out KAYNAR3:code dilsun$ ./a.out 0 0 -1342177280 -805306368 0 0 -1342177280 -805306368 -1232863216 -1232863216 Initializing memory

void print_memory_int(int* start_ptr, int num) { int *ptr = start_ptr; for (int i = 0; i < num; i++) { printf("%d\n", *ptr); ptr = ptr + 1; } }

int *A = xcalloc(5, sizeof(int)); print_memory_int(A,5); xcalloc behaves like alloc_array in C0.

KAYNAR3:code dilsun$ ./a.out 0 0 0 0 0 Undefined behaviors

int *A = xcalloc(5,sizeof(int)); printf(“A[-10000] is %d",A[-10000] );

KAYNAR3:code dilsun$ ./a.out 0 0 0 0 0 Segmentation fault: 11

Safety violations in C0 are undefined behavior in C. Examples of undefined behavior

• Reading/writing to non-allocated memory

• Reading uninitialized memory (even if correctly allocated)

• Using memory that has beed freed

• Double free Aliasing

int *A = xmalloc(sizeof(int)*5); A[1] = 7; A[2] = A[1] + 5; A[4] = 1 int *B = A + 2;

A 0xBB0 0xBB4 0xBB8 0xBBC 0xBC0

… 7 12 1 … A[0] A[1] A[2] A[3] A[4] B[0] B[1] B[2] Pointer casting

int *A = xmalloc(sizeof(int)*5); A[1] = 7; A[2] = A[1] + 5; A[4] = 1 char *C = (char *)A;

A 0xBB0 0xBB4 0xBB8 0xBBC 0xBC0

… 7 12 1 … A[0] A[1] A[2] A[3] A[4]

printf("Charater at index 16: %d\n",C[16]); prints 1 but depends on how integers are represented struct point { int x; int y; Pointer casting };

struct point *D = (struct point *) (A+2);

A 0xBB0 0xBB4 0xBB8 0xBBC 0xBC0

… 7 12 1 … A[0] A[1] A[2] A[3] A[4]

D[0] D[1]

printf("(x1,y1) = (%d, %d)\n", D[0].x, D[0].y); prints (x1,y1) = (12, 0) struct point { int x; int y; Pointer casting };

struct point *D = (struct point *) (A+2);

A 0xBB0 0xBB4 0xBB8 0xBBC 0xBC0

… 7 12 1 … A[0] A[1] A[2] A[3] A[4]

D[0] D[1]

printf("(x1,y1) = (%d, %d)\n", D[1].x, D[1].y); prints (x1,y1) = (1, ?) Out of bound access Stack allocated arrays

In C0, arrays and structs can only be allocated on the heap.

In C, arrays and structs can also be allocated on the stack.

int E[10]; E[0] = 3;

int F[] = {2, 4, 56, 8, 3}; F[4] = 10; struct point p; p.x = 3; p.y = 7; printf("p is (%d, %d)\n", p.x, p.y); Strings in C (different ways to create them)

On the heap: char *s1 = xmalloc(4*sizeof(char)); s1[0] = 'c'; s1[1] = 'a'; s1[2] = ’t'; s1[3] = '\0';

On the stack: char s2[] = {'d', 'o', 'g', '\0'}; char s3[] = "pig";

In read-only text: char *s3 = “fox" Exercise: Where is the data stored?

char *s1 = xmalloc(3*sizeof(char)); heap

char s2[] = {'d', 'o', 'g', '\0'}; stack

char *s3 = "fox"; read-only text

char s4[] = "pig"; stack &: “Address of” operator

In C0, & can be used only to get address of functions. In C, it can be used to get address of any value that has a memory address.

OS restricted int i = 42; H 0xB4B main H 0xB4B hdict_lookup Local increment(&i); STACK k 0x73C i 0 memory k1 0x73C key_equiv k2 0x735 increment(&p.y);

2 4 Allocated HEAP memory 0x735 0x73C increment(&A[3]); 73 42 "hamlet" read-only TEXT "rose" main … hdict_lookup … CODE key_hash … read-only key_equiv … OS restricted Transition to C

LOST GAINED

Contracts Preprocessor

Safety Explicit memory management

Garbage collection Tools: valgrind

Memory initialization Pointer arithmetics

Tools: Interpreter (coin) Stack allocated arrays and structs

Well-behaved arrays Generalized “address of”

Fully defined language

Strings