Linked data structures. EECS 211 Winter 2019

Similar documents
Dynamic memory. EECS 211 Winter 2019

The C++ Object Lifecycle. EECS 211 Winter 2019

Dynamic Memory Management. Bin Li Assistant Professor Dept. of Electrical, Computer and Biomedical Engineering University of Rhode Island

COSC Software Engineering. Lecture 16: Managing Memory Managers

CSE 333 Midterm Exam Sample Solution 7/28/14

Princeton University Computer Science 217: Introduction to Programming Systems. Data Structures

Advanced Pointer Topics

ECE 264 Exam 2. 6:30-7:30PM, March 9, You must sign here. Otherwise you will receive a 1-point penalty.

Programs in memory. The layout of memory is roughly:

Debugging (Part 2) 1

Lecture 14 Notes. Brent Edmunds

Intermediate Programming, Spring 2017*

Memory (Stack and Heap)

CS24 Week 2 Lecture 1

Armide Documentation. Release Kyle Mayes

Memory Allocation in C C Programming and Software Tools. N.C. State Department of Computer Science

ECE551 Midterm Version 1

ECE 551D Spring 2018 Midterm Exam

Q1: /8 Q2: /30 Q3: /30 Q4: /32. Total: /100

CSCI-243 Exam 1 Review February 22, 2015 Presented by the RIT Computer Science Community

Memory Management in C (Dynamic Strings) Personal Software Engineering

Dynamic Data Structures (II)

CS 241 Data Organization Binary Trees

In Java we have the keyword null, which is the value of an uninitialized reference type

Short Notes of CS201

Dynamic Memory & ADTs in C. The heap. Readings: CP:AMA 17.1, 17.2, 17.3, The primary goal of this section is to be able to use dynamic memory.

Dynamic Memory & ADTs in C

Pointers and Memory Management

CS61, Fall 2012 Section 2 Notes

CS201 - Introduction to Programming Glossary By

Implementing an abstract datatype. Linked lists and queues

Memory Management. CS449 Fall 2017

ECE 551D Spring 2018 Midterm Exam

ECE551 Midterm. There are 7 questions, with the point values as shown below. You have 75 minutes with a total of 75 points. Pace yourself accordingly.

TI2725-C, C programming lab, course

Data Structures in C. C Programming and Software Tools. N.C. State Department of Computer Science

Princeton University Computer Science 217: Introduction to Programming Systems. Modules and Interfaces

19-Nov CSCI 2132 Software Development Lecture 29: Linked Lists. Faculty of Computer Science, Dalhousie University Heap (Free Store)

CS 61C: Great Ideas in Computer Architecture C Memory Management, Usage Models

Recitation #11 Malloc Lab. November 7th, 2017

Mid-term Exam. Fall Semester 2017 KAIST EE209 Programming Structures for Electrical Engineering. Name: Student ID:

Dynamic Allocation of Memory

Dynamic Memory & ADTs in C

Key C Topics: Tutorial Pointers, Dynamic Memory allocation, Valgrind and Makefile CS370

Memory Organization. The machine code and data associated with it are in the code segment

Signature: ECE 551 Midterm Exam

CSci 4061 Introduction to Operating Systems. Programs in C/Unix

ECE 2400 Computer Systems Programming Fall 2018 Topic 6: C Dynamic Allocation

Kurt Schmidt. October 30, 2018

ECE551 Midterm Version 2

CIS 2107 Computer Systems and Low-Level Programming Fall 2011 Midterm

Lecture 8 Dynamic Memory Allocation

6.S096: Introduction to C/C++

Dynamic Allocation of Memory

cc -o build/test_translate build/test_translate.o b... $

Welcome! COMP s1. Programming Fundamentals

Fundamentals of Programming

Fall 2018 Discussion 2: September 3, 2018

CS 11 C track: lecture 5

Dynamic Memory Allocation

Section 2: Processes

APS105. Malloc and 2D Arrays. Textbook Chapters 6.4, Datatype Size

Week 9 Part 1. Kyle Dewey. Tuesday, August 28, 12

o Code, executable, and process o Main memory vs. virtual memory

CSE 374 Final Exam Sample Solution 3/15/12

CSE 374 Final Exam 3/15/17 Sample Solution. Question 1. (8 points) Suppose we have the following two statements in a C program:

Scientific Programming in C IV. Pointers

C Structures & Dynamic Memory Management

Memory. What is memory? How is memory organized? Storage for variables, data, code etc. Text (Code) Data (Constants) BSS (Global and static variables)

Understanding Pointers

Mid-term Exam. Fall Semester 2017 KAIST EE209 Programming Structures for Electrical Engineering. Name: Student ID:

Memory Allocation. General Questions

ECE264 Spring 2014 Exam 2, March 11, 2014

CSC 270 Survey of Programming Languages. What is a Pointer?

ECE264 Fall 2013 Exam 3, November 20, 2013

ENCM 339 Fall 2017 Tutorial for Week 8

(13-2) Dynamic Data Structures I H&K Chapter 13. Instructor - Andrew S. O Fallon CptS 121 (November 17, 2017) Washington State University

A Capacity: 10 Usage: 4 Data:

User created Heap Management in C on AIX

CSCI-UA /2. Computer Systems Organization Lecture 19: Dynamic Memory Allocation: Basics

Dynamic Data Structures. CSCI 112: Programming in C

CSC209H Lecture 3. Dan Zingaro. January 21, 2015

Heap Arrays and Linked Lists. Steven R. Bagley

CSC 1600 Memory Layout for Unix Processes"

Pointers, Dynamic Data, and Reference Types

Hacking in C. Memory layout. Radboud University, Nijmegen, The Netherlands. Spring 2018

CS61C : Machine Structures

Programming in C. Lecture 5: Aliasing, Graphs, and Deallocation. Dr Neel Krishnaswami. Michaelmas Term University of Cambridge

High Performance Computing and Programming, Lecture 3

Midterm Exam Nov 8th, COMS W3157 Advanced Programming Columbia University Fall Instructor: Jae Woo Lee.

ECE551 Midterm Version 1

CS 222: Pointers and Manual Memory Management

The assignment requires solving a matrix access problem using only pointers to access the array elements, and introduces the use of struct data types.

Both parts center on the concept of a "mesa", and make use of the following data type:

Warmup January 9th, What is the value of the following C expression? 8*9 % 10/ 2

Singly linked lists in C.

Binghamton University. CS-211 Fall Dynamic Memory

CP2 Revision. theme: dynamic datatypes & data structures

CS201 Some Important Definitions

Actually, C provides another type of variable which allows us to do just that. These are called dynamic variables.

Transcription:

Linked data structures EECS 211 Winter 2019

2 Initial code setup $ cd eecs211 $ curl $URL211/lec/07linked.tgz tar zx $ cd 07linked

Preliminaries 3

4 Two views on malloc and free The client/c view: malloc(n) gives you an abstract reference to a shiny, new, never-before-seen object of n bytes. free(p) destroys the object *p, never to be seen again.

4 Two views on malloc and free The client/c view: malloc(n) gives you an abstract reference to a shiny, new, never-before-seen object of n bytes. free(p) destroys the object *p, never to be seen again. The implementation/machine view: malloc(n) searches a huuuge array of bytes for an unused section of size n, makes a note that the section is now used, and returns its address. free(p) marks the section that p refers to unused again.

5 valgrind(1) is a memory debugger $

5 valgrind(1) is a memory debugger $ cat oops.c

5 valgrind(1) is a memory debugger $ cat oops.c #include <stdlib.h> int main() { malloc(211); $

5 valgrind(1) is a memory debugger $ cat oops.c #include <stdlib.h> int main() { malloc(211); $ cc -o oops oops.c

5 valgrind(1) is a memory debugger $ cat oops.c #include <stdlib.h> int main() { malloc(211); $ cc -o oops oops.c $

5 valgrind(1) is a memory debugger $ cat oops.c #include <stdlib.h> int main() { malloc(211); $ cc -o oops oops.c $./oops

5 valgrind(1) is a memory debugger $ cat oops.c #include <stdlib.h> int main() { malloc(211); $ cc -o oops oops.c $./oops $

5 valgrind(1) is a memory debugger $ cat oops.c #include <stdlib.h> int main() { malloc(211); $ cc -o oops oops.c $./oops $ valgrind./oops

valgrind(1) is a memory debugger $ cat oops.c #include <stdlib.h> int main() { malloc(211); $ cc -o oops oops.c $./oops $ valgrind./oops ==25879== HEAP SUMMARY: ==25879== in use at exit: 211 bytes in 1 blocks ==25879== total heap usage: 1 allocs, 0 frees, 211 bytes ==25879== ==25879== LEAK SUMMARY: ==25879== definitely lost: 211 bytes in 1 blocks ==25879== indirectly lost: 0 bytes in 0 blocks ==25879== possibly lost: 0 bytes in 0 blocks ==25879== still reachable: 0 bytes in 0 blocks ==25879== suppressed: 0 bytes in 0 blocks ==26289== Rerun with --leak-check=full to see details of le 5

The main event 6

7 How can we deal with growing data? malloc returns a fixed-sized array

7 How can we deal with growing data? malloc returns a fixed-sized array So how does, say, read_line work?

7 How can we deal with growing data? malloc returns a fixed-sized array So how does, say, read_line work? It reallocates and copies as needed

Simplification of read_line char* read_line(void) { size_t cap = 0; size_t size = 0; char* buffer = NULL; for (;;) { if (size + 1 > cap) { cap = cap? (2 * cap) : CAPACITY0; buffer = realloc_or_die(buffer, cap); int c = getchar(); if (c == EOF c == '\n') { buffer[size] = '\0'; return buffer; else buffer[size++] = (char) c; 8

9 The real, slightly more efficient read_line char* read_line(void) { int c = getchar(); if (c == EOF) return NULL; size_t cap = CAPACITY0; size_t size = 0; char* buffer = realloc_or_die(null, cap); for (;;) { if (c == EOF c == '\n') { buffer[size] = '\0'; return buffer; else buffer[size++] = (char) c; c = getchar(); if (size + 1 > cap) { cap *= 2; buffer = realloc_or_die(buffer, cap);

10 The alternative Doubling a big buffer is highly performant.

10 The alternative Doubling a big buffer is highly performant. (Only not growing at all would be better.)

10 The alternative Doubling a big buffer is highly performant. (Only not growing at all would be better.) But it s not smooth, and it s not very flexible, so there s an alternative: Instead of one big allocation, lots of small allocations, pointing to each other.

11 Remember this? ; length : [List-of X] -> Nat ; Finds the length of a list. (define (length lst) (if (empty? lst) 0 (+ 1 (length (rest lst)))))

11 Remember this? ; length : [List-of X] -> Nat ; Finds the length of a list. (define (length lst) (if (empty? lst) 0 (+ 1 (length (rest lst))))) (length (cons 2 (cons 3 (cons 4 '())))

12 Here s how it works* struct cons_pair { int car; struct cons_pair* cdr; ;

12 Here s how it works* typedef struct cons_pair* list_t; struct cons_pair { int car; struct cons_pair* cdr; ;

12 Here s how it works* typedef struct cons_pair* list_t; struct cons_pair { int car; list_t cdr; ;

12 Here s how it works* In cons.h: typedef struct cons_pair* list_t; In cons.c: struct cons_pair { int car; list_t cdr; ;

13 cons == malloc + initialization #include <stdlib.h> list_t cons(int first, list_t rest) { list_t result = malloc(sizeof *result); if (result == NULL) bail out ; result->car = first; result->cdr = rest; return result;

14 empty = NULL* const list_t empty = NULL;

15 Using cons and empty #include "cons.h" int main() { list_t m = cons(2, cons(3, cons(4, empty)));

15 Using cons and empty #include "cons.h" int main() { list_t m = cons(2, cons(3, cons(4, empty))); car 2 car 3 car 4 m cdr cdr cdr

15 Using cons and empty #include "cons.h" int main() { list_t m = cons(2, cons(3, cons(4, empty))); // Now what? car 2 car 3 car 4 m cdr cdr cdr

16 We need predicates and selectors bool is_empty(list_t lst) { return lst == NULL; bool is_cons(list_t lst) { return lst!= NULL; int first(list_t lst) { assert( lst ); return lst->car; list_t rest(list_t lst) { assert( lst ); return lst->cdr;

17 A whole list program #include "cons.h" #include <stdio.h> int main() { list_t m = cons(2, cons(3, cons(4, empty))); while (is_cons(m)) { printf("%d\n", first(m)); m = rest(m);

17 A whole list program, or is it? #include "cons.h" #include <stdio.h> int main() { list_t m = cons(2, cons(3, cons(4, empty))); while (is_cons(m)) { printf("%d\n", first(m)); m = rest(m);

18 List fun, 111 style #include "cons.h" size_t list_len(list_t lst) { return is_empty(lst)? 0 : 1 + list_len(rest(lst));

18 List fun, 111 style #include "cons.h" size_t list_len(list_t lst) { return is_empty(lst)? 0 : 1 + list_len(rest(lst)); (define (length lst) (if (empty? lst) 0 (+ 1 (length (rest lst)))))

List fun, 211 style 19

19 List fun, 211 style (define (length-acc acc lst) (if (empty? lst) acc (length-acc (+ 1 acc) (rest lst)))) (define (length lst) (length-acc 0 lst))

19 List fun, 211 style (define (length-acc acc lst) (if (empty? lst) acc (length-acc (+ 1 acc) (rest lst)))) (define (length lst) (length-acc 0 lst)) size_t list_len(list_t lst) { size_t result = 0; while (is_cons(lst)) { lst = rest(lst); ++result; return result;

20 Freeing a list, recursively Back to cons.c

20 Freeing a list, recursively Back to cons.c void uncons_all(list_t lst) { if (lst) { free(lst); uncons_all(lst->cdr); void uncons_all(list_t lst) { if (lst) { uncons_all(lst->cdr); free(lst);

20 Freeing a list, recursively Back to cons.c void uncons_all(list_t lst) //Fully broken { if (lst) { free(lst); uncons_all(lst->cdr); void uncons_all(list_t lst) //Semi-broken, but { //go with it for now if (lst) { uncons_all(lst->cdr); free(lst);

21 What s wrong with this program? #include "cons.h" int main() { list_t m = cons(3, cons(4, empty)); list_t n = rest(m); uncons_all(m); printf("%d\n", first(n)); uncons_all(n);

22 What about this program? #include "cons.h" int main() { list_t m = cons(3, cons(4, empty)); list_t n = cons(2, m); printf("%d\n", first(n)); uncons_all(n); printf("%d\n", first(m)); uncons_all(m);

22 What about this program? #include "cons.h" int main() { list_t m = cons(3, cons(4, empty)); list_t n = cons(2, m); printf("%d\n", first(n)); uncons_all(n); printf("%d\n", first(m)); uncons_all(m); Idea: Owners and borrowers.

23 Ownership protocol The owner of a heap-allocated object is responsible for deallocating it. (No one else may.)

23 Ownership protocol The owner of a heap-allocated object is responsible for deallocating it. (No one else may.) When passing a pointer, it may or may not transfer ownership

23 Ownership protocol The owner of a heap-allocated object is responsible for deallocating it. (No one else may.) When passing a pointer, it may or may not transfer ownership: If it does, then the caller must pass a heap-allocated object that it owns, giving up ownership.

23 Ownership protocol The owner of a heap-allocated object is responsible for deallocating it. (No one else may.) When passing a pointer, it may or may not transfer ownership: If it does, then the caller must pass a heap-allocated object that it owns, giving up ownership. If it does not, then the caller need not own the object, as the callee merely borrows it, and no ownershp changes.

23 Ownership protocol The owner of a heap-allocated object is responsible for deallocating it. (No one else may.) When passing a pointer, it may or may not transfer ownership: If it does, then the caller must pass a heap-allocated object that it owns, giving up ownership. If it does not, then the caller need not own the object, as the callee merely borrows it, and no ownershp changes. The only way to tell which is which is to read the contract.

23 Ownership protocol The owner of a heap-allocated object is responsible for deallocating it. (No one else may.) When passing a pointer, it may or may not transfer ownership: If it does, then the caller must pass a heap-allocated object that it owns, giving up ownership. If it does not, then the caller need not own the object, as the callee merely borrows it, and no ownershp changes. The only way to tell which is which is to read the contract. Functions can also return either owned or borrowed pointers.

24 Ownership in cons.h // Takes ownership of `rest`, returns owned list: list_t cons(int first, list_t rest);

24 Ownership in cons.h // Takes ownership of `rest`, returns owned list: list_t cons(int first, list_t rest); // Borrows `lst`, just for call: bool is_empty(list_t lst), is_cons(list_t lst); int first(list_t lst);

24 Ownership in cons.h // Takes ownership of `rest`, returns owned list: list_t cons(int first, list_t rest); // Borrows `lst`, just for call: bool is_empty(list_t lst), is_cons(list_t lst); int first(list_t lst); // Borrows `lst` and returns borrowed sub-part: list_t rest(list_t lst);

24 Ownership in cons.h // Takes ownership of `rest`, returns owned list: list_t cons(int first, list_t rest); // Borrows `lst`, just for call: bool is_empty(list_t lst), is_cons(list_t lst); int first(list_t lst); // Borrows `lst` and returns borrowed sub-part: list_t rest(list_t lst); // Takes ownership of `lst` (and all it points to): void uncons_all(list_t lst);

24 Ownership in cons.h // Takes ownership of `rest`, returns owned list: list_t cons(int first, list_t rest); // Borrows `lst`, just for call: bool is_empty(list_t lst), is_cons(list_t lst); int first(list_t lst); // Borrows `lst` and returns borrowed sub-part: list_t rest(list_t lst); // Takes ownership of `lst` (and all it points to): void uncons_all(list_t lst); // Takes ownership of `lst`, and returns owned // version of `rest(lst)`: list_t uncons_one(list_t lst);

25 Implementations of unconsing list_t uncons_one(list_t lst) { free(lst); return lst->cdr;

25 Implementations of unconsing list_t uncons_one(list_t lst) { free(lst); return lst->cdr; //UB!

25 Implementations of unconsing list_t uncons_one(list_t lst) { free(lst); return lst->cdr; //UB! list_t uncons_one(list_t lst) { list_t next = lst->cdr; free(lst); return next;

void uncons_all(list_t lst) { while (lst) lst = uncons_one(lst); 25 Implementations of unconsing list_t uncons_one(list_t lst) { free(lst); return lst->cdr; //UB! list_t uncons_one(list_t lst) { list_t next = lst->cdr; free(lst); return next;

26 The fixed program #include "cons.h" int main() { list_t m = cons(3, cons(4, empty)); list_t n = uncons_one(m); printf("%d\n", first(n)); uncons_all(n);

26 The fixed program #include "cons.h" int main() { list_t m = cons(3, cons(4, empty)); list_t n = uncons_one(m); printf("%d\n", first(n)); uncons_all(n);

Next time: RAII 27

28 Notes * Lies