feudal c automatic memory management with zero runtime overhead cs263 - spring 1999 scott mcpeak dan...
TRANSCRIPT
Feudal C
Automatic memory management with zero runtime overhead
CS263 - Spring 1999
Scott McPeak Dan BonacheaCarol Hurwitz
C
Outline
• Introduction - Ownership and the Owner Tree
• Goals of Feudal C
• Syntax, Type Rules, and Operational Semantics
• Examples
• Memory Safety Theorem and Proof Outline
The Basic Idea• Designate some pointers as "owners"
– Obligation to delete the pointed-at object: no memory leaks
• The rest of the pointers are "serfs"– No deletion obligation (or capability)– Must stop pointing at an object before it is
deleted: no dangling pointers
• Use the type system– Enforce the distinction (type soundness)– Enforce properties of both kinds
Ownership and the Owner TreeGlobals
main()
foo()
bar()
bigArray
A B C
localObj
dl1 dl2 dl3 dl4
owner
serf
Flavors• Owners:
• Serfs:
• This project:– Prove memory safety of restricted versions
• No leaks
• No dangling references
– Simplify language
exclusive restricted normal
efficient flexible
restricted static dynamic full RC
efficient flexible
Goals of Feudal C
• Provide memory safety (no leaks, no dangling references) through static typing
• Promote clear design practices
• Enable passing memory out of a function
• Still have a language that’s useful
Language Syntax• Types
TypeAux ::= int | t owner * t TypeAux
Type ::= t | t serf * t TypeAux
• Typical Imperative Commands & Expressions– if-then-else – Assignment (copy & transfer)
– while – Arithmetic & Boolean Expressions (no side effects)
– new / delete – Function call & return
• Rules of Thumb (enforced by typing)– No serf pointers stored in the heap or returned from functions
– No owner pointers as parameters to functions
– Dereferencing serf pointers gets only serf pointers
• Limitations:– No Arrays – No “Legacy” Pointers
– No Records – No Function types or pointers
– No address-of operator – No Recursive Types (*)
Small Example
int owner* owner* allocSmallList(int val) {int owner* x; // variable declarations
int owner* owner* y;
x := new int; // allocate an integer on the heap
*x = val; // store val there
y := new int owner*; // create a pointer on the heap
*y := x; // this nullifies x
return y; // safely returns allocated space!
}
Partial Typing Rules
|- v1 : owner * |- v2 : owner *
|- F v1 := v2
Transfer Assign Command |- v : owner * serf *
|- *v : serf *
Serf Pointer Dereference
|- e : int |-F c1 |-F c2
|-F if e then c1 else c2
Conditional Command
|- x : serf * |- e : owner *
|-F x = e
Copy Assign Command
|- x : owner * |- e : serf *
|- F x = e
Note: This rule does not exist! f ( x1 : 1, ... , xn : n ) xn+1 : n+1, ... , xm : m c ; rc F
= x1 : 1, ... , xm : m
|-F c |- rc : ´ serf * 1 i n . i i´ owner *
|-F f
Function Definition
Partial Operational Semantics
n(x) = 0 ( hr newaddr ) dom( H )
1, ... , n | H | x := new ; c 1, ... , n [ ( ohr newaddr ) / x ] | H { ( ( hr newaddr ), 0 ) } | c
Allocation Command
f ( x1, ... , xm ) xm+1, ... , xp cbody Fop
1 i m . eval( ei, n, H ) vi m+1 i p . vi = 0
1, ... , n | H | x = f ( e1, ... , em ) ; c 1, ... , n, Frame ( { (x1, v1)... , (xp, vp) }, c , x ) | H | cbody
Function Call Command
y dom(n) . y x n(y) (ohr z)
val = n(x)
1, ... , n-1, n | H | return x 1, ... , n-1[ val / n.var ] | H | n.cmd
Function Return Command
Values = (ohr ) (shr ) 0 or 4 or (ohr 37) or (shr 5)
VarValueMap = P(Loc Values) VVM = { (x, 5), (y, (shr 17)) , (z, (ohr 17))}
Frame = VarValueMap Command Loc n = Frame(VVM, c, x)
Heap = P ((hr ) Values) H = { ((hr 16), 2), ((hr 30), (ohr 17)) }
States = Frame list Heap Command S = 1, ... , n | H | c
Framework
Memory Safety Roadmap
Lemma 1:Single owner,
no cycles
No Memory LeaksNo DanglingReferences
Memory SafetyT heorem
Lemma 2:No serfs
pointing down
Lemma 3:No serfs on heap
Used forinduction
ImpliedDirectly
Used forinduction
Used for induction
By Induction on Typing Rules andOperational Sem antics
By TypeS oundness
Single Owner, No Cycles Lemma
• Lemma 1: For every allocated element, there is exactly one owner pointing to it from the heap or from the stack, and there exist no cycles.
( hr n) dom(H). |owners((hr n))| = 1 and (hr n) TC ((hr n))
• Initial State:
< Frame( {(x,0)}, return y, y ) | | x = main(); return x >
Since the heap is empty the lemma is vacuously true for the base case
Single Owner, No Cycles Lemma
x (ohr 5)(ohr 7)
0
5
7
beforeafter
v
…
TC(x)
objaddr
targetaddr
x 0(ohr 7)
(ohr 5)
5
7
v
…
TC(x)
objaddr
targetaddr
*v := x
y dom(n) n(y) = (ohr objaddr)
eval( v, n, H ) (ohr targetaddr) H((hr targetaddr)) = 0
(hr targetaddr) TC( H, (hr objaddr) )
1, ... , n | H | *v := y ; c 1, ... , n [ 0 / y ] | H [ (ohr objaddr) / (hr targetaddr) ] | c
Transfer Assign Command
No Memory Leaks
• Defn: A memory leak is allocated memory which is not reachable from the stack, i.e., is not in the transitive closure of anything on the stack.
– Theorem: Feudal C is safe with respect to memory leaks.
• Initial state:– The heap is empty when the program begins, so they is no allocated memory, and hence no
memory leaks.
No Dangling References
x
y
(ohr 5)
(shr 7)
(ohr 7) (ohr 13) 0
5 7 13
Not allowed
x
y
0
0
beforeafter
n(x) = (ohr addr)
y dom(n) . y x n(y) = (shr z) (hr z) TC(H, (hr addr))
1, ... , n | H | delete ( x ) ; c 1, ... , n [ 0 / x ] | del ( H, (ohr addr) ) | c
DeAllocation Command