Upload
eelco-visser
View
110
Download
2
Tags:
Embed Size (px)
DESCRIPTION
lecture 3 in concepts of programming languages course at TU Delft
Citation preview
TI1220 2012-2013Concepts of Programming Languages
Eelco Visser / TU Delft
Lecture 3: Variables and Storage
OutlineMessages from the labVariables & storageCopy & reference semanticsLifetimeLocal & heap memoryMemory management(Memory and pointers in C)
Deadline: final date that assignment can be submitted without penalty
Due date (new): advise date for finishing assignment to help you plan your work
http://en.wikipedia.org/wiki/File:Computer_system_bus.svg
Von Neumann Architecture: stored-program computer in which an instruction fetch and a data operation cannot occur
at the same time because they share a common bus
Storage Cellunique addressstatus: allocated or unallocatedcontent: storable value or undefined
63
‘foo’
?
false
primitive variable
composite variable
unallocated cell
undefined
storable value: can be stored in single storage cell
C++: primitive values and pointers
Java: primitive values and pointers to objects
Typically: composite values are not storable
simple variable: a variable that may contain a storable value; occupies a single storage cell
{ int n; n = 0; n = n + 1;}
?
0
1
terminology: “the content of the storage cell denoted by n” ~ “the value of n”
C
composite variable: a variable of a composite type, occupies a
group of contiguous cells
struct Date { int y, m, d;}struct Date today;today.m = 2; today.d = 26;today.y = 2013;
struct Date dates[3];dates[0].y = 2013;dates[0].m = 1;dates[0].d = 31;dates[1] = today;
2013
2
26
ymd
today
2013
1
31
ymd
2013
2
26
ymd
?
?
?
ymd
dates[0]
dates[1]
dates[2]
dates
C
struct Date { int y, m, d;}struct Date today, tomorrow;
tomorrow = today;
tomorrow.d = today.d + 1;
total update: updating composite variable with a new value in a single step
selective update: updating single component of a composite variable
C
static array: array variable whose index range is fixed at compile-time
float v1[] = {2.0, 3.0, 5.0, 7.0};float v2[10];
void print_vector(float v[], int n) { printf("[%3.2f", v[0]); for(int i = 1; i < n; i++) { printf(" %3.2f", v[i]); } printf("]");}
print_vector(v1, 4);print_vector(v2, 10);
C
type Vector is array (Integer range <>) of Float;
v1: Vector(1 .. 4) := (2.0, 3.0, 5.0, 7.0);v2: Vector(0 .. m) := (0 .. m => 0.0);
procedure print_vector(v: in Vector) is -- Print the array v in the form "[...]".begin put('['); put(v(v'first)); for i in v'first + 1 .. v'last loop put(' '); put(v(i)); end loop put(']');end;print_vector(v1); print_vector(v2);
dynamic array: array variable whose index range is fixed at the time when the array is created
Ada
float[] v1 = {2.0, 3.0, 5.0, 7.0};float[] v2 = {0.0, 0.0, 0.0};
v1 = v2; // changes index range of v1
static void printVector(float[] v) { System.out.print("[" + v[0]); for(int i = 1; i < v.length; i++) { System.out.print(" " + v[i]); } System.out.print("]");}
printVector(v1);printVector(v2);
flexible array: array variable whose index range is not fixed, may change when new array value is assigned
Java
copy semantics: assignment copies all components of composite value into
corresponding components of composite variable
struct Date { int y, m, d;}struct Date dateA = {2013, 2, 31};struct Date dateB;dateB = dateA; // copy assignment
struct Date *dateP = malloc(sizeof(struct Date));struct Date *dateQ = malloc(sizeof(struct Date));*dateP = dateA; // copy assignmentdateQ = dateP; // reference assignment
C
draw this
reference semantics: assignment makes composite variable contain a pointer (or reference) to the composite value
class Date { int y, m, d; public Date(int y, int m, int d) { // ... }}
Date dateR = new Date(2013, 1, 31);Date dateS = new Date(2012, 11, 26);dateS = dateR; // reference assignment
Date dateT = new Date(2013, 4, 9);dateT = dateR.clone(); // copy assignment
Java
draw this
equality test should be consistent with semantics of assignment
under copy semantics equality test is structural: tests whether corresponding components of two
composite values are equal
under reference semantics equality test tests whether the pointers to the two
composite values are equal
lifetime of a variable: interval between creation (allocation) and destruction (deallocation)
global variable: declared for use throughout the program; lifetime is program’s run-time
local variable: declared within a block, for use only within that block; lifetime is activation of block
heap variable: can be created and destroyed at any time during the program’s run-time; arbitrary lifetime bound by program run-time
persistent variable: lifetime transcends activation of a program
Persistent variables in WebDSL
WebDSL (http://webdsl.org) is a high-level web programming language developed at TU Delft
entity Assignment { key :: String (id) title :: String (name, searchable) shortTitle :: String description :: WikiText (searchable) course -> CourseEdition (searchable) weight :: Float (default=1.0) deadline :: DateTime (default=null) // ...} page assignment(assign: Assignment, tab: String) { main{ progress(assign, tab) pageHeader{ output(assign.title) breadcrumbs(assign) } // ... } }
Persistent variables in WebDSL
http://department.st.ewi.tudelft.nl/weblab/assignment/752
objects are automatically persisted in database
1
2
3
Variable
• holds value
• needs memory for storage during lifetime
Allocation
• obtain memory for storage of variable value
Deallocation
• give memory back
Error: use deallocated variable
Allocation and Deallocation
Function call
• memory allocated for all locals
• locals = parameters + local variables
During execution of function
• memory for locals allocated even if another function is called
Function exit
• locals are deallocated
• end of scope for locals is reached
// Local storage exampleint Square(int num) { int result; result = num * num; return result;}
Rules for Local Storage
void Foo(int a) { // (1) Locals (a, i, scores) allocated when Foo runs
int i;
float scores[100]; // This array of 100 floats is allocated locally.
a = a + 1; // (2) Local storage is used by the computation
for (i = 0; i < a; i++) { Bar(i + a); // (3) Locals continue to exist undisturbed, } // even during calls to other functions.
} // (4) The locals are all deallocated when the function exits.
C
void X() { int a = 1; int b = 2; // T1 Y(a); // T3 Y(b); // T5}void Y(int p) { int q; q = p + 2; // T2 (first time through), // T4 (second time through)} Stack Frames
Advantages
• Convenient: temporary memory for lifetime of function
• Efficient: fast allocation and deallocation, no waste of space
• Local copies: parameters are pass by value
Disadvantages
• Short lifetime: cannot be used for more permanent storage
• Restricted communication: cannot report back to caller
Synonyms
• “automatic” variables
• stack variables
Local Memory
// TAB -- The Ampersand Bug function// Returns a pointer to an intint* TAB() { int temp; return (&temp); // return a pointer to the local int}void Victim() { int* ptr; ptr = TAB(); *ptr = 42; // Runtime error! The pointee was local to TAB}
Escaping Locals
int x = 1, y = 2, z[10];
int *ip; /* ip is a pointer to int */
ip = &x; /* ip now points to x */
y = *ip; /* y is now 1 */
*ip = 0; /* x is now 0 */
ip = &z[0]; /* ip now points to z[0] */
*ip = *ip + 10; /* z[0] incremented with 10 */
Dereferencing Pointers
#define ALLOCSIZE 10000 /* size of available space */static char allocbuf[ALLOCSIZE]; /* storage for alloc */static char *allocp = allocbuf; /* next free position */char *alloc(int n) /* return pointer to n characters */{ if (allocbuf + ALLOCSIZE - allocp >= n) { /* it fits */ allocp += n; return allocp - n; /* old p */ } else /* not enough room */ return 0;}void afree(char *p) /* free storage pointed to by p */{ if (p >= allocbuf && p < allocbuf + ALLOCSIZE) allocp = p;}
Pointer Arithmetic
Heap memory = dynamic memory
• allocated at run-time
Advantages
• Lifetime: programmer controls memory allocation, deallocation
• Size: allocate amount of memory needed at run-time
Disadvantages
• More work: manage the heap
• More bugs: ... under control of programmer ...
void Heap1() { int* intPtr; // Allocates local pointer local variable (but not its pointee) // Allocates heap block and stores its pointer in local variable. // Dereferences the pointer to set the pointee to 42. intPtr = malloc(sizeof(int)); *intPtr = 42; // Deallocates heap block making the pointer bad. // The programmer must remember not to use the pointer // after the pointee has been deallocated (this is // why the pointer is shown in gray). free(intPtr);}
void Heap1() { int* intPtr; // Allocates local pointer local variable (but not its pointee) // Allocates heap block and stores its pointer in local variable. // Dereferences the pointer to set the pointee to 42. intPtr = malloc(sizeof(int)); *intPtr = 42; // Deallocates heap block making the pointer bad. // The programmer must remember not to use the pointer // after the pointee has been deallocated (this is // why the pointer is shown in gray). free(intPtr);}
void Heap1() { int* intPtr; // Allocates local pointer local variable (but not its pointee) // Allocates heap block and stores its pointer in local variable. // Dereferences the pointer to set the pointee to 42. intPtr = malloc(sizeof(int)); *intPtr = 42; // Deallocates heap block making the pointer bad. // The programmer must remember not to use the pointer // after the pointee has been deallocated (this is // why the pointer is shown in gray). free(intPtr);}
void Heap1() { int* intPtr; // Allocates local pointer local variable (but not its pointee) // Allocates heap block and stores its pointer in local variable. // Dereferences the pointer to set the pointee to 42. intPtr = malloc(sizeof(int)); *intPtr = 42; // Deallocates heap block making the pointer bad. // The programmer must remember not to use the pointer // after the pointee has been deallocated (this is // why the pointer is shown in gray). free(intPtr);}
Heap
• Area of memory to allocate blocks of memory for program
• Heap manager: manages internals of heap
• Free list: private data structure for heap management
• Heap may get full
• requests for more memory fail
• Allocated block reserved for caller
• location and size fixed
• Deallocation gives block back to heap manager
• deallocated blocks should not be used
Programming the Heap
void *malloc(size_t n);// returns a pointer to n bytes of uninitialized storage, // or NULL if the request cannot be satisfied
void *calloc(size_t n, size_t size);// returns a pointer to enough free space for // an array of n objects of the specified size, // or NULL if the request cannot be satisfied. // The storage is initialized to zero.
void free(void *ap);// frees the space pointed to by p, where p was // originally obtained by a call to malloc or calloc.
int *ip;ip = (int *) calloc(n, sizeof(int));// allocated memory should be cast to appropriate type
Memory Management API
K&R: a sample implementation
void HeapArray() { struct fraction* fracts; int i; // allocate the array fracts = malloc(sizeof(struct fraction) * 100); // use it like an array -- in this case set them all to 22/7 for (i = 0; i < 99; i++) { fracts[i].numerator = 22; fracts[i].denominator = 7; } // Deallocate the whole array free(fracts);}
Allocating Array on Heap
/* Given a C string, return a heap allocated copy of the string. Allocate a block in the heap of the appropriate size, copies the string into the block, and returns a pointer to the block. The caller takes over ownership of the block and is responsible for freeing it. */char* StringCopy(const char* string) { char* newString; int len; len = strlen(string) + 1; // +1 to account for the '\0' newString = malloc(sizeof(char) * len); // elem-size * number-of-elements assert(newString != NULL); // simplistic error check (a good habit) strcpy(newString, string); // copy the passed in string to the block return (newString); // return a ptr to the block}
dynamic size
long lifetime
Allocating String on Heap
typedef long Align; /* for alignment to long boundary */
union header { /* block header */ struct { union header *ptr; /* next block if on free list */ unsigned size; /* size of this block */ } s; Align x; /* force alignment of blocks */};typedef union header Header;
static Header base; /* empty list to get started */static Header *freep = NULL; /* start of free list */
Free List
Memory is allocated, but not deallocated
• heap gradually fills up
• program runs out of heap space
• crash
Ownership
• stringCopy() does not own allocated memory
• caller is responsible for deallocation
Memory management
• requires careful administration of memory allocated
Memory Leaks
lifetime of a variable: interval between creation (allocation) and destruction (deallocation)
global variable: declared for use throughout the program; lifetime is program’s run-time
local variable: declared within a block, for use only within that block; lifetime is activation of block
heap variable: can be created and destroyed at any time during the program’s run-time; arbitrary lifetime bound by program run-time
persistent variable: lifetime transcends activation of a program