Korrekte Software: Grundlagen und Methoden Vorlesung 12 vom 25.06.19 Referenzen und Speichermodelle
Serge Autexier, Christoph Lüth Universität Bremen Sommersemester 2019
17:10:57 2019-07-10 1 [29]
Fahrplan
IEinführung
IOperationale Semantik IDenotationale Semantik
IÄquivalenz der Operationalen und Denotationalen Semantik IDer Floyd-Hoare-Kalkül
IInvarianten und die Korrektheit des Floyd-Hoare-Kalküls IStrukturierte Datentypen
IVerifikationsbedingungen IVorwärts mit Floyd und Hoare IModellierung
ISpezifikation von Funktionen IReferenzen und Speichermodelle
IFunktionsaufrufe und das Framing-Problem IAusblick und Rückblick
Korrekte Software 2 [29]
Motivation
IWarum Referenzen?
INötig fürcall by reference
IFunktion können sonst nurglobaleSeiteneffekte haben IEffizienz
IKurze Begriffsklärung:
IReferenzen: getypt, eingeschränkte Arithmetik IZeiger: ungetypt, Zeigerarithmetik
Korrekte Software 3 [29]
Refenzen in C
IPointer in C (“pointer type”):
ISchwach getypt (void∗kompatibel mit allen Zeigertypen, Typumwandlung)
IEingeschränkte Zeigerarithmetik (Addition, Subtraktion) IFelder werden durch Zeigerarithmetik implementiert
IPointer sindfirst-class-values
IC-Standard läßt das Speichermodell relativ offen IRepräsentation von Objekten
Korrekte Software 4 [29]
Referenzen in anderen Sprachen
IJava:
IAlles ist eine Referenz
ISchwach getypt (Subtyping und Typumwandlung) IHaskell, SML, OCaml:
IStark getypt (typsicher) IScriptsprachen (Python, Ruby):
IÄhnlich Java
Korrekte Software 5 [29]
Ausdrücke
INeue Operatoren: Addressoperator (&a) und Derefenzierung (∗l) Lexpl::=Idt|l[a]|l.Idt|∗a
Aexpa::=Z|C|Lexp|&l
|a1+a2|a1−a2|a1∗a2|a1/a2|Idt(Exp∗) Bexp b::=. . .
Expe:=Aexp|Bexp Stmtc::=. . .
Typet::=char|int|∗t|structIdt?{Decl+} |tIdt[a]
Korrekte Software 6 [29]
Das Problem mit Zeigern
IBisheriges Speichermodell: Σ =Loc*V IAliasing:
Verschiedene Bezeichner (Lexp) für die gleiche Lokationl∈Loc i n t a ;
i n t ∗p ;
p= &a ; a= 0 ; //{a= 0}
∗p= 7 ; //{a= 7}
IWert von a ändert sichohne dass aerwähntwird.
IGroßes Problem für Semantik und Hoare-Kalkül.
Korrekte Software 7 [29]
Erweiterung des Zustandmodells
IBisheriger Zustand Σ=defLoc*Vmit ILocations:Loc::=Idt|Loc[Z]|Loc.Idt IWerte:V=Z
IAnsatz reicht nicht mehr:
(i)Werte müssen auch Locations sein:Vdef=Z+Loc
(ii)Idtals Location nicht ausreichend für Referenzen und Funktionen IMan kann den Zustandmodellbasiert(wie bisher) oderaxiomatisch
beschreiben.
Korrekte Software 8 [29]
Axiomatisches Zustandsmodell
IDer Zustand ist ein abstrakter Datentyp Σ (undLoc) mit zwei Operationen und folgenden Gleichungen:
read: Σ→Loc*V upd: Σ→Loc→V*Σ
Vdef=Z+Loc
read(upd(σ,l,v),l) =v l6=m=⇒read(upd(σ,l,v),m) =read(σ,m)
upd(upd(σ,l,v),l,w) =upd(σ,l,w)
l6=m=⇒upd(upd(σ,l,v),m,w) =upd(upd(σ,m,w),l,v)
IDiese Gleichungen sindvollständig.
Korrekte Software 9 [29]
Axiomatisches Speichermodell
IEs gibt einenleerenSpeicher, und neue (“frische”) Adressen:
empty: Σ fresh: Σ→Loc
rem: Σ→Loc→Σ IfreshmodelliertAllokation,remmodelliertDeallokation Idombeschreibt denDefinitionsbereich:
dom(σ) ={l| ∃v.read(σ,l) =v}
dom(empty) =∅
IEigenschaften vonempty,freshundrem:
fresh(σ)6∈dom(σ) dom(rem(σ,l)) =dom(σ)\ {l}
l6=m=⇒read(rem(σ,l),m) =read(σ,m)
Korrekte Software 10 [29]
Zeigerarithmetik
IZiegerarithmetik: Rechnen mit Zeigern IImplementiert Felder und Strukturen IWir betrachten keineDifferenzvon Zeigern
add:Loc→Z→Loc
add(l,0) =l
add(add(l,a),b) =add(l,a+b) add(l,a) =l=⇒a= 0 add(l,a) =add(l,b) =⇒a=b
Korrekte Software 11 [29]
Erweiterung der Semantik
IProblem:Lochaben unterschiedliche Semantik auf der linken oder rechten Seite einer Zuweisung.
Ix = x+1 — Links: Addresse der Variablen, rechts: Wert an dieser Adresse
ILösung in C: “Except when it is (. . . ) the operand of the unary &
oprerator, the left operand of the . operator or an assigment operator, an lvalue that does not have array type is converted to the value stored in the designated object (and is no longer an lvalue)”
C99 Standard, §6.3.2.1 (2)
INicht spezifisch für C
Korrekte Software 12 [29]
Umgebung
IFür Funktionen brauchten wir eineUmgebung(Environment):
Env=Id*[[FunDef]]
=Id*VN*Σ*(Σ×Vu)
IDiese muss erweitert werden für Variablen:
Env=Id*([[FunDef]]]Loc)
IInsbesondere: gleicher Namensraum für Funktionen und Variablen (C99 Standard, §6.2.3)
Korrekte Software 13 [29]
Erweiterung der Semantik: Lexp
L[[−]] :Env→Lexp→Σ*Loc
L[[x]] Γ ={(σ,Γ!x)|σ∈Σ}
L[[lexp[a]]] Γ ={(σ,add(l,i·sizeof(τ)))|(σ,l)∈ L[[lexp]] Γ,(σ,i)∈ A[[a]] Γ}
type(Γ,lexp) =τist der Basistyp des Feldes L[[lexp.f]] Γ ={(σ,l.f)|(σ,add(l,fld_off(τ,f)))∈ L[[lexp]] Γ}
type(Γ,lexp) =τist der Typ der Struktur L[[∗e]] Γ =A[[e]] Γ
Itype(Γ,e) ist derTypeines Ausdrucks
Ifld_off(τ,f) ist derOffsetdes Feldesf in der Strukturτ Isizeof(τ) ist dieGrößevon Objekten des Typsτ
Korrekte Software 14 [29]
Erweiterung der Semantik: Aexp(1)
A[[−]] :Env→Aexp→Σ*V
A[[n]] Γ ={(σ,n)|σ∈Σ} fürn∈N A[[e]] Γ ={(σ,read(σ,l))|(σ,l)∈ L[[e]] Γ}
e∈Lexpundtype(Γ,e) kein Array-Typ A[[e]] Γ ={(σ,l)|(σ,l)∈ L[[e]] Γ}
e∈Lexpundtype(Γ,e) Array-Typ A[[&e]] Γ ={(σ,l)|(σ,l)∈ L[[e]] Γ}
Korrekte Software 15 [29]
Erweiterung der Semantik: Aexp(2)
A[[−]] :Env→Aexp→Σ*V
A[[a0+a1]] Γ ={(σ,n0+n1|(σ,n0)∈ A[[a0]] Γ∧(σ,n1)∈ A[[a1]] Γ}
A[[a0−a1]] Γ ={(σ,n0−n1)|(σ,n0)∈ A[[a0]] Γ∧(σ,n1)∈ A[[a1]] Γ}
A[[a0∗a1]] Γ ={(σ,n0∗n1)|(σ,n0)∈ A[[a0]] Γ∧(σ,n1)∈ A[[a1]] Γ}
A[[a0/a1]] Γ ={(σ,n0/n1)|(σ,n0)∈ A[[a0]] Γ∧(σ,n1)∈ A[[a1]] Γ
∧n16= 0}
Korrekte Software 16 [29]
Und jetzt?
IZustand erweitert, so dass wir Zeiger modellieren können.
ISemantik entsprechend erweitert.
IWas machen wir mit dem Hoare-Kalkül, speziell derZuweisung?
IVorherige Modellierung — Zuweisung durch Substitution modelliert — nicht mehr ausreichend.
IDaher:explizite Zustandsprädikate
Korrekte Software 17 [29]
Explizite Zustandsprädikate
IZusicherungenen (Assn) sind zustandsabhängige Prädikate
IMit anderen Worten, Prädikate über Programmvariablen.
IAxiomatische Beschreibung des Zustandes erforderte neue Modellierung auf der Ebene der Prädikate
IExplizite Zustandsprädikate modellieren die Zustandsoperationenread undupdexplizit
Korrekte Software 18 [29]
Explizite Zustandsprädikate
IErweiterung vonAexpvumread, neue SorteStatemit Operation upd:
Lexps l::=. . .| ∗a Assns b::=. . .
Aexps a::=read(S,l)|Z|C|l| &l |. . .|\old(e)|. . . State S::=StateVar|upd(S,l,e)
IZustandsvariablenStateVar: Aktueller Zustandσ, Vorzustandρ IExplizite Zustandsprädikate enthalten kein∗oder &
IDamit Semantik:
Bsp[[.]] :Env→Assns*(Σ×(Σ×VU))→B Asp[[.]] :Env→Aexps*(Σ×(Σ×VU))→V
Korrekte Software 19 [29]
Hoare-Triple
Γ|={P}c{Q|R}
IP,Q,R∈Assnssindexplizite Zustandsprädikate
IDeklarationen (Decl) allozieren für jede Variable eine Location (fresh), und ordnen diese in Γ dem Namen zu.
IGültigkeit von Hoare-Tripeln (partielle, totale Korrektheit) wie vorher
Korrekte Software 20 [29]
Floyd-Hoare-Kalkül mit expliziten Zustandsprädikaten
Γ` {Q[upd(σ,x,e)/σ]}x=e{Q|R}
IEinLexplauf der rechten Seiteewird durchread(σ,l) ersetzt.1 I&dient lediglich dazu, diese Konversion zu verhindern.
I∗erzwingt diese Konversion, auch auf der linken Seitex.
IBeispiel:∗a =∗&b;
1Außerlist ein Array-Typ.
Korrekte Software 21 [29]
Formal: Konversion in Zustandsprädikate
(−)†:Lexp→Lexps i†=i (i∈Idt) l.id†=l†.id l[e]†=l†[e#]
∗l†=l#
(−)#:Aexp→Aexps e#=read(σ,e†) (e∈Lexp) n#=n
v#=v (vlogische Variable)
&e#=e† e1+e2#=e1#+e2#
\result#=\result
\old(e)#=\old(e)
Korrekte Software 22 [29]
Angepasste Regeln des Hoare-Kalküls
Γ` {Q[upd(σ,x†,e#)/σ]}x=e{Q|R}
Γ` {Q[e#/\result]}return e{P|Q}
Korrekte Software 23 [29]
Zwei kurze Beispiele
v o i d f o o ( ) { i n t x , y , z ; //{true}
z= x ; x= 0 ; z= 5 ; y= x ; //{y= 0}
}
v o i d f o o ( ) { i n t x , y , ∗z ; //{true}
z= &x ; x= 0 ;
∗z= 5 ; y= x ; //{y= 5}
Korrekte Software 24 [29]
Ein problematisches Beispiel
v o i d f o o (i n t ∗p ) {
i n t x ; //{true}
x= 7 ;
∗p= 9 9 ; //{x= 7}
}
IKönnenwederbeweisen, dass
∗p=xnoch∗p6=x
IErfordert Spezifikation: wenn∗p auf eingültigesObjekt zeigt, dann∗p6=xdaxlokale Variable.
IGenerelles Problem — was ist mit v o i d f o o (i n t ∗p , i n t ∗q ) { . . . }
IKönnen weder beweisen, dass
∗p=∗qnoch∗p6=∗q
Korrekte Software 25 [29]
Weitere Beispiele: Felder
i n t f i n d m a x (i n t a [ ] , i n t a _ l e n ) /∗∗ p r e \array(a,a_len)∧0<a_len; ∗/
/∗∗ p o s t ∀i.0≤i<a_len−→a[i]≤\result; ∗/
{
i n t x ; i n t j ; x= INT_MIN ; j= 0 ; w h i l e ( j < a _ l e n )
/∗∗ i n v (∀i.0≤i<j−→a[i]≤x)∧j≤a_len; ∗/
{
i f ( a [ j ]> x ) x= a [ j ] ; j= j +1;
} r e t u r n x ; }
Korrekte Software 26 [29]
Felder und Zeiger revisited
IIn C sind Zeiger und Felder schwach spezifiziert IInsbesondere:
Ia[ j ]=∗(a+j) für a Array-Typ
IDerefenzierung von∗x nur definiert, wenn x “gültig” ist (d.h. auf ein Objekt zeigt)C99 Standard, §6.5.3.2(4)
IBisher in den Hoare-Regeln ignoriert —partielleKorrektheit.
IIst das sinnvoll? Nein, bekannte Fehlerquelle
Korrekte Software 27 [29]
Spezifikation von Zeigern und Feldern
Das Prädikat\valid(x)
\valid(x)⇐⇒read(σ,x†) ist definiert
IInsbesondere:\valid(∗x)⇐⇒read(σ,read(σ,x)) ist definiert.
IFelder als Parameter werden Zeigern konvertiert, deshalb müssen wir spezifizieren können, dass ein Zeiger “in Wirklichkeit” ein Feld ist.
I\array(a,n) bedeutet: a ist ein Feld der Länge n, d.h.
\array(a,n)⇐⇒(∀i.0≤i<n=⇒\valid(a[i]))
IValidität kann abgeleitet werden:
x= &e
\valid(*x)
\array(a, n) 0≤i i<n
\valid(a[i])
Korrekte Software 28 [29]
Zusammenfassung
IUm Referenzen (Pointer) in C behandeln zu können, benötigen wir ein erweitertesZustandsmodell
IReferenzen werden zu Werten wie Zahlen oder Zeichen.
IArrays und Strukturen sindkeinefirst-class values.
IGroßes Problem:aliasing
IErweiterung der Semantik und der Hoare-Tripel nötig:
IVor/Nachbedingungen werden zuexpliziten Zustandsprädikaten.
IZuweisung wird zuZustandsupdate.
IProblem:
I Zustände werdensehr groß
I Rückwärtsrechnung erzeugt schnell sehr große „unbestimmte“ Zustände, die nicht vereinfacht werden können
I Hier ist Vorwärtsrechnung vorteilhaft
Korrekte Software 29 [29]