Checking correctness properties of object-oriented programs K. Rustan M. Leino Microsoft Research, Redmond, WA Lecture 4 EEF summer school on Specification, Refinement, and Verification 23 Aug.

Download Report

Transcript Checking correctness properties of object-oriented programs K. Rustan M. Leino Microsoft Research, Redmond, WA Lecture 4 EEF summer school on Specification, Refinement, and Verification 23 Aug.

Checking correctness properties
of object-oriented programs
K. Rustan M. Leino
Microsoft Research, Redmond, WA
Lecture 4
EEF summer school on Specification, Refinement, and Verification
23 Aug 2002, Turku, Finland
Programming methodology



Restricts programs by imposing a
programming discipline
Can simplify concepts involved in
reasoning about programs
Not always a match for all good programs,
because:


the methodology may not be adequately
formalized, and
programming methodologies evolve
Valid/state paradigm
class T {
abstract field valid: bool
abstract field state: unit
constructor T(this, x, y, z)
requires P(x,y,z) modifies this.valid, this.state ensures this.valid
method operation0(this, x, y, z)
requires this.valid /\ R0(x,y,z) modifies this.state ensures true
method operation1(this, x, y, z)
requires this.valid /\ R1(x,y,z) modifies this.state ensures true
…
field f: int in valid, state
field g: int in valid, state
field h: int in state
rep this.valid  this.f < this.g
…}
The role of valid
class T {
abstract field valid: bool
abstract field state: unit
constructor T(this, x, y, z)
requires P(x,y,z) modifies this.valid, this.state ensures this.valid
method operation0(this, x, y, z)
requires this.valid /\ R0(x,y,z) modifies this.state ensures true
method operation1(this, x, y, z)
requires this.valid /\ R1(x,y,z) modifies this.state ensures true
…
field f: int in valid, state
field g: int in valid, state
field h: int in state
rep this.valid  this.f < this.g
…}
Object invariants
class T {
abstract field state: unit
constructor T(this, x, y, z)
requires P(x,y,z) modifies this.state ensures true
method operation0(this, x, y, z)
requires R0(x,y,z) modifies this.state ensures true
method operation1(this, x, y, z)
requires R1(x,y,z) modifies this.state ensures true
…
field f: int in state
field g: int in state
Methodology:
field h: int in state
invariant this.f < this.g
…}
an object invariant
“always” holds
When should invariants hold?
class T {
field x, y, z: int
invariant this.x = this.y + this.z
…
}
On procedure boundaries
Which procedure boundaries?
class T {
field v: Vector
field w: Vector
invariant this.v.size = this.w.size
}
method check(this) { assert this.v.size = this.w.size }
method m(this) { this.v.extend(E); this.w.extend(F) }
class Vector {
abstract field size: int
method extend(this, x)
requires true modifies this.size ensures this.size = this.size0 + 1
}
Which procedure boundaries?
class T {
field v: Vector
field w: Vector
invariant this.v.size = this.w.size
}
method check(this) { assert this.v.size = this.w.size }
method m(this) { this.v.extend(E); this.w.extend(this) }
class Vector {
abstract field size: int
method extend(this, x)
requires true modifies this.size ensures this.size = this.size0 + 1
mimpl extend(this, x) {
x.check();
…
}
}
Constructors
class T <: S {
field x: int
field y: int
invariant this.x ≤ this.y
constructor T(this, a: int, b: int) {
this.S();
if a ≤ b then
this.x := a; this.y := b
else
this.x := b; this.y := a
end;
this.p()
}
}
method p(this) requires true modifies ε ensures true
Constructors: a further subclass
class U <: T {
field m: int
field n: int
invariant this.m < this.n
constructor U(this) {
this.T(12, 6);
this.m := 20;
this.n := 21
}
}
mimpl p(this) {
assert this.m < this.n
}
Close methods
class T {
abstract field valid: bool
abstract field state: unit
}
constructor T(this)
requires true modifies this.valid, this.state ensures this.valid
method m(this)
requires this.valid modifies this.state ensures true
method close(this)
requires this.valid modifies this.valid, this.state ensures true
…
var t in
t := new(T);
t.m();
t.close();
t.m()
// error
end
The role of state
class T {
abstract field state: unit
constructor T(this, x, y, z)
requires P(x,y,z) modifies this.state ensures true
method operation0(this, x, y, z)
requires R0(x,y,z) modifies this.state ensures true
method operation1(this, x, y, z)
requires R1(x,y,z) modifies this.state ensures true
…
field f: int in state
field g: int in state
field h: int in state
invariant this.f < this.g
}
…
Can state be “hidden”?
Summary: invariants





simple concept
tricky to get rules right
language designers beware: design
constructors carefully!
does not (alone) handle close methods
requires more research
Concurrency


Multiple threads running in parallel,
reading and writing shared data
Mutual exclusion provided by mutexes
(locks)
var mu: Mutex
…
lock mu do // acquire mu
S
end
// release mu
Concurrency: race conditions

A race condition occurs when a shared
variable is written by one thread and
concurrently read or written by another
thread
Avoid race conditions



Methodology: Every shared variable is
protected by some declared mutex
var mu: Mutex
var x monitored_by mu
lock mu do
…x…
end
Concurrency: deadlocks

A deadlock occurs when a set of threads
each waits for a mutex that another
thread holds
Avoiding deadlocks

Methodology:


partially order the mutexes
in each thread, acquire mutexes in ascending
order
var mu0: Mutex
var mu1: Mutex
declare mu0 < mu1
…
lock mu1 do
lock mu0 do
…
end
end
// error
Updating mutexes
var mu: Mutex
var x monitored_by mu
Thread 0:
Thread 1:
lock mu do
x := E
end
mu := new(Mutex);
lock mu do
x := F
end
Monitor state
var mu: Mutex
var x monitored_by mu
…
lock mu do
x := 10
end;
lock mu do
assert x = 10
end
havoc x;
// error
Changing the order
class Node {
field x monitored_by this;
field left: Node
field right: Node
declare this < this.left
declare this < this.right
method balance(this) …
Summary: concurrency




simple ideas
methodology allows for sequential
reasoning
tricky in dynamic situations
needs more research
Summary


Semantic checkers for object-oriented
languages are possible
Methodology requires more work
References






David L. Detlefs, K. Rustan M. Leino, Greg Nelson, and James B.
Saxe. Extended static checking. Research Report 159, Compaq
SRC, Dec. 1998.
K. Rustan M. Leino and Greg Nelson. Data abstraction and
information hiding. Research Report 160, Compaq SRC, Nov. 2000.
To appear in TOPLAS.
Bertrand Meyer. Object-oriented Software Construction.
International Series in Computer Science, Prentice Hall, 1988.
K. Rustan M. Leino and Raymie Stata. Checking object invariants.
Technical Note 1997-007, DEC SRC, Jan. 1997.
K. Rustan M. Leino, Greg Nelson, and James B. Saxe. ESC/Java
User’s Manual. Technical Note 2000-002, Compaq SRC, Oct. 2000.
Cormac Flanagan, K. Rustan M. Leino, Mark Lillibridge, Greg Nelson,
James B. Saxe, and Raymie Stata. “Extended static checking for
Java”. In PLDI ’02, SIGPLAN Notices 37(5), pp. 234-245, ACM, May
2002.
References

Gary T. Leavens, Albert L. Baker, and Clyde Ruby. Preliminary
Design of JML: A Behavioral Interface Specification Language for
Java. Department of Computer Science, Iowa State University, TR


#98-06r, Aug. 2002.
K. Rustan M. Leino. “A myth in the modular specification of
programs”. Unpublished manuscript KRML 63, DEC SRC, Nov. 1995.
Available from author.
C.A.R. Hoare. “Monitors: an operating system structuring concept”.
CACM 17(10), pp. 549-557, ACM, Oct. 1974.