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

Similar documents
Class Information ANNOUCEMENTS

CS 33. Intro to Storage Allocation. CS33 Intro to Computer Systems XXVI 1 Copyright 2017 Thomas W. Doeppner. All rights reserved.

Heap Arrays. Steven R. Bagley

Dynamic memory. EECS 211 Winter 2019

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

Operating System Labs. Yuanbin Wu

Programming in C. 4. Misc. Library Features, Gotchas, Hints and Tips. Dr. Neel Krishnaswami University of Cambridge

Heap Arrays and Linked Lists. Steven R. Bagley

Fundamental of Programming (C)

Memory (Stack and Heap)

Dynamic Memory Management

Dynamic Data Structures (II)

CSCI 2132 Software Development. Lecture 29: Dynamic Memory Allocation

C for Java Programmers 1. Last Week. Overview of the differences between C and Java. The C language (keywords, types, functies, etc.

Solution for Data Structure

Programming in C. Lecture 6: The Memory Hierarchy and Cache Optimization. Dr Neel Krishnaswami. Michaelmas Term

CS61, Fall 2012 Section 2 Notes

Chapter 20: Binary Trees

UNIVERSITY OF TORONTO FACULTY OF APPLIED SCIENCE AND ENGINEERING

Memory Management. CSC215 Lecture

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

ECE 250 / CS 250 Computer Architecture. C to Binary: Memory & Data Representations. Benjamin Lee

SYSC 2006 C Winter 2012

Procedural programming with C

CS32 Discussion Sec.on 1B Week 2. TA: Zhou Ren

Lecture 8 Dynamic Memory Allocation

l Determine if a number is odd or even l Determine if a number/character is in a range - 1 to 10 (inclusive) - between a and z (inclusive)

Informatics 1 Functional Programming Lecture 4. Lists and Recursion. Don Sannella University of Edinburgh

ECE264 Spring 2013 Final Exam, April 30, 2013

CS61C : Machine Structures

Singly linked lists in C.

How about them A s!! Go Oaktown!! CS61C - Machine Structures. Lecture 4 C Structures Memory Management Dan Garcia.

C PROGRAMMING Lecture 5. 1st semester

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

Implementing an abstract datatype. Linked lists and queues

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

APS105. Structures 11/18/2013. Example A struct of stock items at a store: Structures. Lists. Arrays allow a collection of elements

Data Structure Series

CS113: Lecture 9. Topics: Dynamic Allocation. Dynamic Data Structures

Midterm II Exam Principles of Imperative Computation Frank Pfenning. March 31, 2011

An Introduction to Trees

Advanced Pointer Topics

CS 314 Principles of Programming Languages. Lecture 11

CS61C : Machine Structures

Dynamic Memory Allocation

Reference slides! C Strings! A string in C is just an array of characters.!!!char string[] = "abc";! How do you tell how long a string is?!

Memory Management. CS31 Pascal Van Hentenryck CS031. Lecture 19 1

Memory Allocation III

Linked List using a Sentinel

COMP 524 Spring 2018 Midterm Thursday, March 1

COSC Software Engineering. Lectures 14 and 15: The Heap and Dynamic Memory Allocation

Quiz 0 Review Session. October 13th, 2014

CS61C : Machine Structures

Character Strings. String-copy Example

CS61C Machine Structures. Lecture 4 C Pointers and Arrays. 1/25/2006 John Wawrzynek. www-inst.eecs.berkeley.edu/~cs61c/

CS 11 C track: lecture 5

Linked Data Structures. Linked lists. Readings: CP:AMA The primary goal of this section is to be able to use linked lists and trees.

CS 61C: Great Ideas in Computer Architecture Introduction to C, Part III

CS 31: Intro to Systems Pointers and Memory. Kevin Webb Swarthmore College October 2, 2018

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

Arrays and Memory Management

- 1 - Handout #22S May 24, 2013 Practice Second Midterm Exam Solutions. CS106B Spring 2013

Memory Management. CS449 Fall 2017

COSC345 Software Engineering. The Heap And Dynamic Memory Allocation

Dynamic Memory CMSC 104 Spring 2014, Section 02, Lecture 24 Jason Tang

ECE551 Midterm Version 2

Outline. Briefly review the last class Pointers and Structs Memory allocation Linked lists

Reference slides! Garcia, Fall 2011 UCB! CS61C L04 Introduction to C (pt 2) (1)!

COMP26120: Linked List in C (2018/19) Lucas Cordeiro

Memory Allocation. General Questions

Lecture Notes on Binary Search Trees

CS 31: Intro to Systems Pointers and Memory. Martin Gagne Swarthmore College February 16, 2016

Programming in C. Lecture 9: Tooling. Dr Neel Krishnaswami. Michaelmas Term

Secure Coding in C and C++

Linked data structures. EECS 211 Winter 2019

Programs in memory. The layout of memory is roughly:

CS 237 Meeting 19 10/24/12

Search Trees. Data and File Structures Laboratory. DFS Lab (ISI) Search Trees 1 / 17

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

CS 237 Meeting 18 10/22/12

Lectures 13 & 14. memory management

Lecture Notes CPSC 122 (Fall 2014) Today Quiz 7 Doubly Linked Lists (Unsorted) List ADT Assignments Program 8 and Reading 6 out S.

Fall, 2015 Prof. Jungkeun Park

Data Structures and Algorithms for Engineers

University of Illinois at Urbana-Champaign Department of Computer Science. First Examination

BBM 201 DATA STRUCTURES

Dialects of ML. CMSC 330: Organization of Programming Languages. Dialects of ML (cont.) Features of ML. Functional Languages. Features of ML (cont.

Understanding Pointers

2

Dynamic Memory Allocation and Linked Lists

! Tree: set of nodes and directed edges. ! Parent: source node of directed edge. ! Child: terminal node of directed edge

CMSC 341 Lecture 7 Lists

Functions in C C Programming and Software Tools

Review: C Strings. A string in C is just an array of characters. Lecture #4 C Strings, Arrays, & Malloc

CSC 1600 Memory Layout for Unix Processes"

ECE 15B COMPUTER ORGANIZATION

Lab 4: Tracery Recursion in C with Linked Lists

CS1622. Semantic Analysis. The Compiler So Far. Lecture 15 Semantic Analysis. How to build symbol tables How to use them to find

CMSC 330: Organization of Programming Languages. Functional Programming with Lists

MCS 360 Exam 2 11 November In order to get full credit, you need to show your work.

Transcription:

Programming in C Lecture 5: Aliasing, Graphs, and Deallocation Dr Neel Krishnaswami University of Cambridge Michaelmas Term 2017-2018 1 / 20

The C API for Dynamic Memory Allocation void *malloc(size_t size) Allocate a pointer to an object of size size void free(void *ptr) Deallocate the storage ptr points to 2 / 20

The C API for Dynamic Memory Allocation void *malloc(size_t size) Allocate a pointer to an object of size size void free(void *ptr) Deallocate the storage ptr points to Each allocated pointer must be deallocated exactly once along each execution path through the program. 2 / 20

The C API for Dynamic Memory Allocation void *malloc(size_t size) Allocate a pointer to an object of size size void free(void *ptr) Deallocate the storage ptr points to Each allocated pointer must be deallocated exactly once along each execution path through the program. Once deallocated, the pointer must not be used any more. 2 / 20

One Deallocation Per Path 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int main(void) { 5 int *pi = malloc(sizeof(int)); 6 scanf("%d", pi); // Read an int 7 if (*pi % 2) { 8 printf("even!\n"); 9 free(pi); // WRONG! 10 } 11 } 3 / 20

One Deallocation Per Path 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int main(void) { 5 int *pi = malloc(sizeof(int)); 6 scanf("%d", pi); // Read an int 7 if (*pi % 2) { 8 printf("even!\n"); 9 free(pi); // WRONG! 10 } 11 } This code fails to deallocate pi if *pi is odd 3 / 20

One Deallocation Per Path 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int main(void) { 5 int *pi = malloc(sizeof(int)); 6 scanf("%d", pi); // Read an int 7 if (*pi % 2) { 8 printf("even!\n"); 9 } 10 free(pi); // OK! 11 } This code fails to deallocate pi if *pi is odd Moving it ensures it always runs 3 / 20

A Tree Data Type 1 struct node { 2 int value; 3 struct node *left; 4 struct node *right; 5 }; 6 typedef struct node Tree; 4 / 20

A Tree Data Type 1 struct node { 2 int value; 3 struct node *left; 4 struct node *right; 5 }; 6 typedef struct node Tree; This is the tree type from Lab 4. 4 / 20

A Tree Data Type 1 struct node { 2 int value; 3 struct node *left; 4 struct node *right; 5 }; 6 typedef struct node Tree; This is the tree type from Lab 4. It has a value, a left subtree, and a right subtree 4 / 20

A Tree Data Type 1 struct node { 2 int value; 3 struct node *left; 4 struct node *right; 5 }; 6 typedef struct node Tree; This is the tree type from Lab 4. It has a value, a left subtree, and a right subtree An empty tree is a NULL pointer. 4 / 20

A Tree Data Type 1 Tree *node(int value, Tree *left, Tree *right) { 2 Tree *t = malloc(sizeof(tree)); 3 t->value = value; 4 t->right = right; 5 t->left = left; 6 return t; 7 } 8 void tree_free(tree *tree) { 9 if (tree!= NULL) { 10 tree_free(tree->left); 11 tree_free(tree->right); 12 free(tree); 13 } 14 } 1. Free the left subtree 2. Free the right subtree 3. Free the node itself 5 / 20

A Directed Acyclic Graph (DAG) 1 // Initialize node2 2 Tree *node2 = node(2, NULL, NULL); 3 4 // Initialize node1 5 Tree *node1 = node(1, node2, node2); // node2 repeated! 6 7 // note node1->left == node1->right == node2! 6 / 20

A Directed Acyclic Graph (DAG) 1 // Initialize node2 2 Tree *node2 = node(2, NULL, NULL); 3 4 // Initialize node1 5 Tree *node1 = node(1, node2, node2); // node2 repeated! 6 7 // note node1->left == node1->right == node2! What kind of tree is this? 6 / 20

The shape of the graph node1 left right node2 left right Null Null 7 / 20

The shape of the graph node1 left node2 right node1 has two pointers to node2 left right Null Null 7 / 20

The shape of the graph node1 left node2 right node1 has two pointers to node2 This is a directed acyclic graph, not a tree. left right Null Null 7 / 20

The shape of the graph node1 left left node2 right right node1 has two pointers to node2 This is a directed acyclic graph, not a tree. tree_free(node1) will call tree_free(node2) twice! Null Null 7 / 20

Evaluating free(node1) node1 left right 1 free(node1); node2 left right Null Null 8 / 20

Evaluating free(node1) node1 left node2 right 1 if (node1!= NULL) { 2 tree_free(node1->left); 3 tree_free(node1->right); 4 free(node1); 5 } left right Null Null 8 / 20

Evaluating free(node1) node1 left right 1 tree_free(node1->left); 2 tree_free(node1->right); 3 free(node1); node2 left right Null Null 8 / 20

Evaluating free(node1) node1 left right 1 tree_free(node2); 2 tree_free(node2); 3 free(node1); node2 left right Null Null 8 / 20

Evaluating free(node1) node1 left left node2 right right 1 if (node2!= NULL) { 2 tree_free(node2->left); 3 tree_free(node2->right); 4 free(node2); 5 } 6 tree_free(node2); 7 free(node1); Null Null 8 / 20

Evaluating free(node1) node1 left node2 right 1 tree_free(node2->left); 2 tree_free(node2->right); 3 free(node2); 4 tree_free(node2); 5 free(node1); left right Null Null 8 / 20

Evaluating free(node1) node1 left node2 right 1 tree_free(null); 2 tree_free(null); 3 free(node2); 4 tree_free(node2); 5 free(node1); left right Null Null 8 / 20

Evaluating free(node1) node1 left left node2 right right 1 if (NULL!= NULL) { 2 tree_free(null->left); 3 tree_free(null->right); 4 free(node1); 5 } 6 tree_free(null); 7 free(node2); 8 tree_free(node2); 9 free(node1); Null Null 8 / 20

Evaluating free(node1) node1 left node2 right 1 tree_free(null); 2 free(node2); 3 tree_free(node2); 4 free(node1); left right Null Null 8 / 20

Evaluating free(node1) node1 left right 1 free(node2); 2 tree_free(node2); 3 free(node1); node2 left right Null Null 8 / 20

Evaluating free(node1) node1 left right 1 free(node2); 2 free(node2); 3 free(node1); node2 left right Null Null 8 / 20

Evaluating free(node1) node1 left node2 right 1 free(node2); 2 free(node2); 3 free(node1); node2 is freed twice! left right Null Null 8 / 20

A Tree Data Type which Tracks Visits 1 struct node { 2 bool visited; 3 int value; 4 struct node *left; 5 struct node *right; 6 }; 7 typedef struct node Tree; 9 / 20

A Tree Data Type which Tracks Visits 1 struct node { 2 bool visited; 3 int value; 4 struct node *left; 5 struct node *right; 6 }; 7 typedef struct node Tree; This tree has a value, a left subtree, and a right subtree 9 / 20

A Tree Data Type which Tracks Visits 1 struct node { 2 bool visited; 3 int value; 4 struct node *left; 5 struct node *right; 6 }; 7 typedef struct node Tree; This tree has a value, a left subtree, and a right subtree An empty tree is a NULL pointer. 9 / 20

A Tree Data Type which Tracks Visits 1 struct node { 2 bool visited; 3 int value; 4 struct node *left; 5 struct node *right; 6 }; 7 typedef struct node Tree; This tree has a value, a left subtree, and a right subtree An empty tree is a NULL pointer. it also has a visited field. 9 / 20

Creating Nodes of Tree Type 1 Tree *node(int value, Tree *left, Tree *right) { 2 Tree *t = malloc(sizeof(tree)); 3 t->visited = false; 4 t->value = value; 5 t->right = right; 6 t->left = left; 7 return t; 8 } 1. Constructing a node sets the visited field to false 2. Otherwise returns the same fresh node as before 10 / 20

Freeing Nodes of Tree Type, Part 1 1 typedef struct TreeListCell TreeList; 2 struct TreeListCell { 3 Tree *head; 4 TreeList *tail; 5 } 6 TreeList *cons(tree *head, TreeList *tail) { 7 TreeList *result = malloc(treelistcell); 8 result->head = head; 9 result->tail = tail; 10 return result; 11 } This defines TreeList as a type of lists of tree nodes. cons dynamically allocates a new element of a list. 11 / 20

Freeing Nodes of Tree Type, Part 2 1 TreeList *getnodes(tree *tree, TreeList *nodes) { 2 if (tree == NULL tree->visited) { 3 return nodes; 4 } else { 5 tree->visited = true; 6 nodes = cons(tree, nodes); 7 nodes = getnodes(tree->right, nodes); 8 nodes = getnodes(tree->left, nodes); 9 return nodes; 10 } 11 } 12 / 20

Freeing Nodes of Tree Type, Part 2 1 TreeList *getnodes(tree *tree, TreeList *nodes) { 2 if (tree == NULL tree->visited) { 3 return nodes; 4 } else { 5 tree->visited = true; 6 nodes = cons(tree, nodes); 7 nodes = getnodes(tree->right, nodes); 8 nodes = getnodes(tree->left, nodes); 9 return nodes; 10 } 11 } Add the unvisited nodes of tree to nodes. 12 / 20

Freeing Nodes of Tree Type, Part 2 1 TreeList *getnodes(tree *tree, TreeList *nodes) { 2 if (tree == NULL tree->visited) { 3 return nodes; 4 } else { 5 tree->visited = true; 6 nodes = cons(tree, nodes); 7 nodes = getnodes(tree->right, nodes); 8 nodes = getnodes(tree->left, nodes); 9 return nodes; 10 } 11 } Add the unvisited nodes of tree to nodes. Finish if the node is a leaf or already visited 12 / 20

Freeing Nodes of Tree Type, Part 2 1 TreeList *getnodes(tree *tree, TreeList *nodes) { 2 if (tree == NULL tree->visited) { 3 return nodes; 4 } else { 5 tree->visited = true; 6 nodes = cons(tree, nodes); 7 nodes = getnodes(tree->right, nodes); 8 nodes = getnodes(tree->left, nodes); 9 return nodes; 10 } 11 } Add the unvisited nodes of tree to nodes. Finish if the node is a leaf or already visited Otherwise, add the current node and recurse 12 / 20

Freeing Nodes of Tree Type, Part 3 1 void tree_free(tree *tree) { 2 NodeList *nodes = getnodes(tree, NULL); 3 while (nodes!= NULL) { 4 Tree *head = nodes->head; 5 NodeList *tail = nodes->tail; 6 free(head); 7 free(nodes); 8 nodes = tail; 9 } 10 } 13 / 20

Freeing Nodes of Tree Type, Part 3 1 void tree_free(tree *tree) { 2 NodeList *nodes = getnodes(tree, NULL); 3 while (nodes!= NULL) { 4 Tree *head = nodes->head; 5 NodeList *tail = nodes->tail; 6 free(head); 7 free(nodes); 8 nodes = tail; 9 } 10 } To free a tree, get all the unique nodes in a list 13 / 20

Freeing Nodes of Tree Type, Part 3 1 void tree_free(tree *tree) { 2 NodeList *nodes = getnodes(tree, NULL); 3 while (nodes!= NULL) { 4 Tree *head = nodes->head; 5 NodeList *tail = nodes->tail; 6 free(head); 7 free(nodes); 8 nodes = tail; 9 } 10 } To free a tree, get all the unique nodes in a list Iterate over the list, freeing the nodes 13 / 20

Freeing Nodes of Tree Type, Part 3 1 void tree_free(tree *tree) { 2 NodeList *nodes = getnodes(tree, NULL); 3 while (nodes!= NULL) { 4 Tree *head = nodes->head; 5 NodeList *tail = nodes->tail; 6 free(head); 7 free(nodes); 8 nodes = tail; 9 } 10 } To free a tree, get all the unique nodes in a list Iterate over the list, freeing the nodes Don t forget to free the list! 13 / 20

Freeing Nodes of Tree Type, Part 3 1 void tree_free(tree *tree) { 2 NodeList *nodes = getnodes(tree, NULL); 3 while (nodes!= NULL) { 4 Tree *head = nodes->head; 5 NodeList *tail = nodes->tail; 6 free(head); 7 free(nodes); 8 nodes = tail; 9 } 10 } To free a tree, get all the unique nodes in a list Iterate over the list, freeing the nodes Don t forget to free the list! We re doing dynamic allocation to free some data... 13 / 20

Summary 14 / 20

Summary Freeing trees is relatively easy 14 / 20

Summary Freeing trees is relatively easy Freeing DAGs or general graphs is much harder 14 / 20

Summary Freeing trees is relatively easy Freeing DAGs or general graphs is much harder Freeing objects at most once is harder if there are multiple paths to them. 14 / 20

Arenas 1 struct node { 2 int value; 3 struct node *left; 4 struct node *right; 5 }; 6 typedef struct node Tree; 15 / 20

Arenas 1 struct node { 2 int value; 3 struct node *left; 4 struct node *right; 5 }; 6 typedef struct node Tree; This is the original tree data type 15 / 20

Arenas 1 struct node { 2 int value; 3 struct node *left; 4 struct node *right; 5 }; 6 typedef struct node Tree; This is the original tree data type Let s keep this type, but change the (de)allocatiorn API 15 / 20

Arenas 1 typedef struct arena *arena_t; 2 struct arena { 3 int size; 4 int current; 5 Tree *elts; 6 }; 7 8 arena_t make_arena(int size) { 9 arena_t arena = malloc(sizeof(struct arena)); 10 arena->size = size; 11 arena->current = 0; 12 arena->elts = malloc(size * sizeof(tree)); 13 return arena; 14 } An arena is just a preallocated array of nodes 16 / 20

Arena allocation 1 Tree *node(int value, Tree *left, Tree *right, 2 arena_t arena) { 3 if (arena->current < arena->size) { 4 Tree *t = arena->elts + arena->current; 5 arena->current += 1; 6 t->value = value, t->left = left, t->right = right; 7 return t; 8 } else { 9 return NULL; 10 } 11 } To allocate a node from an arena: 17 / 20

Arena allocation 1 Tree *node(int value, Tree *left, Tree *right, 2 arena_t arena) { 3 if (arena->current < arena->size) { 4 Tree *t = arena->elts + arena->current; 5 arena->current += 1; 6 t->value = value, t->left = left, t->right = right; 7 return t; 8 } else { 9 return NULL; 10 } 11 } To allocate a node from an arena: 1. Initialize current element 17 / 20

Arena allocation 1 Tree *node(int value, Tree *left, Tree *right, 2 arena_t arena) { 3 if (arena->current < arena->size) { 4 Tree *t = arena->elts + arena->current; 5 arena->current += 1; 6 t->value = value, t->left = left, t->right = right; 7 return t; 8 } else { 9 return NULL; 10 } 11 } To allocate a node from an arena: 1. Initialize current element 2. Increment current 17 / 20

Arena allocation 1 Tree *node(int value, Tree *left, Tree *right, 2 arena_t arena) { 3 if (arena->current < arena->size) { 4 Tree *t = arena->elts + arena->current; 5 arena->current += 1; 6 t->value = value, t->left = left, t->right = right; 7 return t; 8 } else { 9 return NULL; 10 } 11 } To allocate a node from an arena: 1. Initialize current element 2. Increment current 3. Return the initialized node 17 / 20

Freeing an Arena 1 void free_arena(arena_t arena) { 2 free(arena->elts); 3 free(arena); 4 } 18 / 20

Freeing an Arena 1 void free_arena(arena_t arena) { 2 free(arena->elts); 3 free(arena); 4 } We no longer free trees individually 18 / 20

Freeing an Arena 1 void free_arena(arena_t arena) { 2 free(arena->elts); 3 free(arena); 4 } We no longer free trees individually Instead, free a whole arena at a time 18 / 20

Freeing an Arena 1 void free_arena(arena_t arena) { 2 free(arena->elts); 3 free(arena); 4 } We no longer free trees individually Instead, free a whole arena at a time All tree nodes allocated from the arena are freed at once 18 / 20

Example 1 arena_t a = make_arena(big_number); 2 3 Tree *node1 = node(0, NULL, NULL, a); 4 Tree *node2 = node(1, node1, node1, a); // it's a DAG now 5 // do something with the nodes... 6 free_arena(a); 19 / 20

Example 1 arena_t a = make_arena(big_number); 2 3 Tree *node1 = node(0, NULL, NULL, a); 4 Tree *node2 = node(1, node1, node1, a); // it's a DAG now 5 // do something with the nodes... 6 free_arena(a); We allocate the arena 19 / 20

Example 1 arena_t a = make_arena(big_number); 2 3 Tree *node1 = node(0, NULL, NULL, a); 4 Tree *node2 = node(1, node1, node1, a); // it's a DAG now 5 // do something with the nodes... 6 free_arena(a); We allocate the arena We can build an arbitrary graph 19 / 20

Example 1 arena_t a = make_arena(big_number); 2 3 Tree *node1 = node(0, NULL, NULL, a); 4 Tree *node2 = node(1, node1, node1, a); // it's a DAG now 5 // do something with the nodes... 6 free_arena(a); We allocate the arena We can build an arbitrary graph And free all the elements at once 19 / 20

Conclusion Correct memory deallocation in C requires thinking about control flow This can get tricky! Arenas are an idiom for (de)allocating big blocks at once Reduces need for thinking about control paths But can increase working set sizes 20 / 20