Korrekte Software: Grundlagen und Methoden Vorlesung 12 vom 09.07.20 Referenzen und Speichermodelle
Serge Autexier, Christoph Lüth Universität Bremen Sommersemester 2020
10:35:18 2020-07-16 1 [42]
Prüfungstermine
IMo, 20.07.2020: Präsenzprüfungen (9:00- 16:30, je zur vollen Stunde)
IDi, 21.07.2020: Onlineprüfungen (9:00- 13:00, alle 30 Minuten)
IMo, 24.08.2020: Präsenzprüfungen (9:00- 16:30, je zur vollen Stunde)
IDi, 25.08.2020: Onlineprüfungen (9:00- 13:00, alle 30 Minuten)
Korrekte Software 2 [42]
Prüfungsmodalitäten
IAnmeldung über stud.ip.
IPräsenzprüfungen:
IIm Raum 4380
IBittenicht vor dem Prüfungsraum versammeln(sondern kurz vorher hochkommen)
IWichtig: Ausweispapiere mitbringen, unten am MZH ausweisen. Eingang ins MZH nur über die Ostseite (zur Enrique-Schmidt-Straße).
IOnlineprüfung:
IÜber Zoom, gleiche Meeting-Id wie gewohnt.
IWir lassen euch zur Prüfung in das Meeting, alle anderen bleiben draussen.
IEine Kamera istzwingenderforderlich.
IDie Prüfung muss in einem ruhigen Raum stattfinden. Es darf sich keine weitere Person im Raum befinden. Hilfsmittel sind nicht zugelassen.
Korrekte Software 3 [42]
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 IAusblick und Rückblick
Korrekte Software 4 [42]
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 5 [42]
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 6 [42]
Referenzen in anderen Sprachen
IJava:
I(Fast) alles ist eine Referenz
ISchwach getypt (Subtyping und Typumwandlung) IHaskell, SML, OCaml:
IStark getypt (typsicher) IScriptsprachen (Python, Ruby):
IÄhnlich Java
Korrekte Software 7 [42]
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 8 [42]
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 vonaändert sichohne dass aerwähntwird.
IAn der Stelle (*) zwei Bezeichner für die gleiche Loc:aund∗p IGroßes Problem für Semantik und
Hoare-Kalkül.
IModellierung der Zuweisung durch Substitution nicht mehr möglich
Korrekte Software 9 [42]
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 Zustandmodellbasiertoderaxiomatischbeschreiben.
Korrekte Software 10 [42]
Speichermodelle I: Konkret (Compiler)
Beispieldeklarationen:
i n t a ; s t r u c t {
i n t x ;
i n t y [ 3 ] } b [ 2 ] ; i n t c [ 3 ] ;
Übersetzung in konkretesSpeicherlayout:
a b c
b[0] b[1] c[0] c[1] c[2]
b[0].x b[0].y b[1].x b[1].y
b[0].y[0] b[0].y[1] b[0].y[2] b[1].y[0] b[1].y[1] b[1].y[2]
0 1 2 3 4 5 6 7 8 9 10 11
Denotatation vonb[0].y[1] ist 3
Korrekte Software 11 [42]
Speichermodelle II: Abstrakt (C-Standard)
Beispieldeklarationen:
i n t a ; s t r u c t {
i n t x ;
i n t y [ 3 ] } b [ 2 ] ; i n t c [ 3 ] ;
Übersetzung in abstraktesSpeicherlayout:
a b c
b[0] b[1] c[0] c[1] c[2]
b[0].x b[0].y b[1].x b[1].y
b[0].y[0] b[0].y[1] b[0].y[2] b[1].y[0] b[1].y[1] b[1].y[2]
l m+0 m+1 m+2 m+3 m+4 m+5 m+6 m+7 n n+1 n+2
Denotatation vonb[0].y[1] istm+ 3, mitmunbestimmteAdresse
Korrekte Software 12 [42]
Speichermodelle III: Symbolisch
Beispieldeklarationen:
i n t a ; s t r u c t {
i n t x ;
i n t y [ 3 ] } b [ 2 ] ; i n t c [ 3 ] ;
Übersetzung in symbolische Adressen:
a b c
b[0] b[1] c[0] c[1] c[2]
b[0].x b[0].y b[1].x b[1].y
b[0].y[0] b[0].y[1] b[0].y[2] b[1].y[0] b[1].y[1] b[1].y[2]
Denotatation vonb[0].y[1] istm[0].y[1], mitmunbestimmte Adresse
Korrekte Software 13 [42]
Abstrakte Zeigerarithmetik
IAdressen sind ein abstrakter DatentypLocso dass:
IEs gibtunbestimmteAdressen IOperationoffaddiert Offset (Feldzugriff) IOperationfldselektiert Feld (struct) IProblem: Gleichheit und Ungleichheit
off:Loc→Z→Loc off(l,0) =l off(off(l,a),b) =off(l,a+b)
off(l,a) =l=⇒a= 0 off(l,a) =off(l,b) =⇒a=b
fld:Loc→Idt→Loc fld(l,f)6=l fld(l,f) =fld(l,g) =⇒f =g fld(l,f) =fld(m,f) =⇒l=m f 6=g=⇒fld(l,f)6=fld(m,g)
Korrekte Software 14 [42]
Arbeitsblatt 12.1: Jetzt mit Zeigern!
Hier eine weitere Folge von Deklarationen:
i n t ∗a [ 1 ] ; s t r u c t {
i n t p [ 2 ] ; s t r u c t {
i n t x ;
i n t y ; } ∗q [ 2 ] ; } b ;
ISkizziert hier das Speichermodell — konkret, abstrakt, symbolisch.
IWelches sind die jeweiligen Adressen (Loc)?
IWas sind die Denotationen füra [1], b.p [1], (∗b.q [0]). x, (∗b.q [1]). y?
IWelche davon sind definiert/undefiniert?
Axiomatisches Zustandsmodell
IDer Zustand ist ein abstrakter Datentyp Σ 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.
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 17 [42]
Erweiterung der Semantik: Umgebung
IFür Funktionen brauchten wir eineUmgebung(Environment):
Env=Idt*[[FunDef]]
=Idt*VN*Σ*(Σ×Vu)
IDiese muss erweitert werden für Variablen:
Env=Idt*([[FunDef]]]Loc)
IInsbesondere: gleicher Namensraum für Funktionen und Variablen (C99 Standard, §6.2.3)
Korrekte Software 18 [42]
Kurze Frage
IWieso modellieren wirLocnicht als Datentyp (so wie bisher):
l::=Idt|l[Z]|l.Idt Dann wäreoff(l,n)def=l[n],fld(l,i)def=l.i.
I[[a]] wäre immera. Damit funktionieren drei Dinge nicht:
1 Wir können globale nicht von lokale Variablen unterscheiden.
2 Beim rekursiven Aufruf wird keine neue Instanz erzeugt.
3 Generell funktioniert call-by-reference nicht, z.B.
v o i d f (i n t ∗x ) {
i n t a ; a= ∗x ; }
v o i d g ( ) {
i n t a ; f (&a ) ; }
Korrekte Software 19 [42]
Erweiterung der Semantik: Problem
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 20 [42]
Erweiterung der Semantik: Lexp
[[−]]L:Env→Lexp→Σ*Loc
[[x]]LΓ ={(σ,Γ!x)|σ∈Σ}
[[lexp[a]]]LΓ ={(σ,off(l,i))|(σ,l)∈[[lexp]]LΓ,(σ,i)∈[[a]]AΓ}
[[lexp.f]]LΓ ={(σ,fld(l,f))|(σ,l)∈[[lexp]]LΓ}
[[∗e]]LΓ =[[e]]AΓ
Korrekte Software 21 [42]
Erweiterung der Semantik: Aexp(1)
[[−]]A:Env→Aexp→Σ*V
[[n]]AΓ ={(σ,n)|σ∈Σ} fürn∈N [[e]]AΓ ={(σ,read(σ,l))|(σ,l)∈[[e]]LΓ}
e∈Lexpundekein Array-Typ [[e]]AΓ ={(σ,l)|(σ,l)∈[[e]]LΓ}
e∈Lexpundeist Array-Typ [[&e]]AΓ ={(σ,l)|(σ,l)∈[[e]]LΓ}
Korrekte Software 22 [42]
Erweiterung der Semantik: Aexp(2)
[[−]]A:Env→Aexp→Σ*V
[[a0+a1]]AΓ ={(σ,n0+n1|(σ,n0)∈[[a0]]AΓ∧(σ,n1)∈[[a1]]AΓ}
[[a0−a1]]AΓ ={(σ,n0−n1)|(σ,n0)∈[[a0]]AΓ∧(σ,n1)∈[[a1]]AΓ}
[[a0∗a1]]AΓ ={(σ,n0∗n1)|(σ,n0)∈[[a0]]AΓ∧(σ,n1)∈[[a1]]AΓ}
[[a0/a1]]AΓ ={(σ,n0/n1)|(σ,n0)∈[[a0]]AΓ∧(σ,n1)∈[[a1]]AΓ
∧n16= 0}
Korrekte Software 23 [42]
Erweiterung der Semantik: Stmt
[[x=e]]CΓ ={(σ,upd(σ,l,a))|(σ,l)∈[[x]]LΓ
∧(σ,a)∈[[e]]AΓ}
[[x=f(t1, . . . ,tn)]]CΓ ={(σ,upd(σ0,l,v))|(σ,(σ0,v))∈Γ(f)(v1, . . . ,vn)
∧(σ,vi)∈[[ti]]AΓ
∧(σ,l)∈[[x]]LΓ}
}
Korrekte Software 24 [42]
Arbeitsblatt 12.2: Pop-Quiz
Gegeben folgende Funktionen:
i n t f (i n t ∗x ) {
i n t a ; a= ∗x ;
∗x= a +1;
r e t u r n a ; }
i n t a [ 3 ] = { 0 , 0 , 0 } ; v o i d g ( )
{
i n t x= 1 ; a [ x ]= f (&x ) ; }
Was ist der Wert des Feldesaam Ende vong?
1 a == {0, 0, 1}
2 a == {0, 0, 2}
3 a == {0, 1, 0}
4 a == {0, 2, 0}
Korrekte Software 25 [42]
Arbeitsblatt 12.3: Kurze Semantik
Gegeben folgende Deklarationen:
s t r u c t { i n t x ; i n t y ; } p [ 5 ] ; i n t a ;
mit folgender Umgebung
Γ=defhp7→l1,a7→l2i,l16=l2 Berechnet die denotationale Semantik von a= a+ p [ 3 ] . x ;
Korrekte Software 26 [42]
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 27 [42]
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 28 [42]
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:
IAktueller Zustandσ, Vorzustandρold, Zwischenzuständeρ0,ρ1,ρ2, . . . IExplizite Zustandsprädikate enthalten kein∗oder&
IIm Gegensatz zur Semantik rechnen wir mitsymbolischen Namen IDamit Semantik:
Bsp[[.]] :Env→Assns*(Σ×(Σ×VU))→B Asp[[.]] :Env→Aexps*(Σ×(Σ×VU))→V
Korrekte Software 29 [42]
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 30 [42]
Floyd-Hoare-Kalkül
Alte Regel
Γ` {Q[upd(σ,x,e)/σ]}x=e{Q|R}
IEinLexplauf der rechten Seiteewird durchread(σ,l) ersetzt.1 I&dient lediglich dazu, diese Konversion zuverhindern.
I∗erzwingtdiese Konversion, auch auf der linken Seitex.
IBeispiel:∗a =∗&b;
1Außerlist ein Array-Typ.
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)
Angepasste Regeln des Hoare-Kalküls
Γ` {Q[upd(σ,x†,e#)/σ]}x=e{Q|R}
Γ` {Q[e#/\result]}return e{P|Q}
Korrekte Software 33 [42]
Arbeitsblatt 12.4: Ein kurzes Beispiel
Betrachtet folgendes Beispiel:
v o i d f o o ( ) { i n t x , y , z ; x= 1 ; z= x ; y= x ; z= 5 ; //{0<y}
}
1 Konvertiert das Prädikat 0<yin ein explizites Zustandsprädikat.
2 Berechnet (rückwärts) die jeweils gültigen Zwischenzustände.
3 Vereinfacht nach jedem Schritt die Zwischenzustände.
Korrekte Software 34 [42]
Ein Beispiel mit Zeigern
v o i d f o o ( ) { i n t x , y , ∗z ; z= &x ; x= 0 ;
∗z= 5 ; y= x ; //{0<y}
Korrekte Software 35 [42]
Ein Beispiel mit Zeigern
v o i df o o ( ) { i n tx , y ,∗z ; /∗∗{ 0< 5 }∗/
/∗∗{ 0< r e a d ( upd ( . . . , x , 5 ) , x ) }∗/
/∗∗{ 0< r e a d ( upd ( upd ( upd ( s , z , x ) , x , 0 ) , x , 5 ) , x ) }∗/
/∗∗{ 0< r e a d ( upd ( upd ( upd ( s , z , x ) , x , 0 ) ,r e a d ( upd ( s , z , x ) , z ) ,5 ) , x ) }∗/
z= &x ;
/∗∗{ 0< r e a d ( upd ( upd ( s , x , 0 ) ,r e a d ( s ,z ) , 5 ) , x ) }∗/
/∗∗{ 0< r e a d ( upd ( upd ( s , x , 0 ) ,r e a d ( s , z ) , 5 ) , x ) }∗/
/∗∗{ 0< r e a d ( upd ( upd ( s , x , 0 ) ,r e a d ( upd ( s , x ,0 ) , z ) , 5 ) , x ) }∗/
x= 0 ;
/∗∗{ 0< r e a d ( upd ( s , r e a d ( s ,z ) , 5 ) , x ) }∗/
∗z= 5 ;
/∗∗{ 0< r e a d ( s , x ) }∗/
/∗∗{ 0< r e a d ( s , x ) }∗/
/∗∗{ 0< r e a d ( upd ( s , y , r e a d ( s , x ) , y ) }∗/
y= x ;
/∗∗{ 0< r e a d ( s , y ) }∗/
}
Korrekte Software 36 [42]
Ein problematisches Beispiel
v o i df o o (i n t∗p ) {
i n t x ;
//{read(upd(upd(s,x,7),read(s,p),99),x) = 7}
//{read(upd(upd(s,x,7),read(upd(s,x,7),p),99),x) = 7}
x= 7 ;
//{read(upd(s,read(s,p),99),x) = 7}
∗p= 9 9 ; //{read(s,x) = 7}
//{x= 7}
}
IKönnenwederbeweisen, dassread(s,p) =xnochread(s,p)6=x IErfordert Spezifikation: wenn∗pauf eingültigesObjekt zeigt, dann
∗p6=xdaxlokaleVariable.
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 37 [42]
Weitere Beispiele: Felder
i n t f i n d m a x (i n t a [ ] , i n t a _ l e n ) /∗∗ pre \array(a,a_len)∧0<a_len; ∗/
/∗∗ post∀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 )
/∗∗ inv (∀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 38 [42]
Felder und Zeiger revisited
IIn C sind Zeiger und Felder schwach spezifiziert IInsbesondere:
Ia[ j ]=∗(a+j)füraArray-Typ
IDerefenzierung von∗xnur definiert, wennx“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 39 [42]
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 zu Zeigern konvertiert, deshalb müssen wir spezifizieren können, dass ein Zeiger ein Feld ist.
I\array(a,n) bedeutet:aist ein Feld der Längen, d.h.
\array(a,n)⇐⇒(∀i.0≤i<n=⇒\valid(a[i]))
IGültigkeit kann abgeleitet werden:
x= &e
\valid(*x)
\array(a, n) 0≤i i<n
\valid(a[i])
Korrekte Software 40 [42]
Was noch fehlt. . .
IVorwärtsrechungmit expliziten Zustandsprädikaten.
IStatt Existenzquantoren über Variablenwerteunbestimmte Zwischenzuständeρ1, ρ2, . . .:
ρi6∈FV(P)
Γ` {P}x=e{P[ρi/σ]∧σ=upd(ρi,x†[ρi/σ],e#[ρi/σ])|R}
IZwischenzustände sindexistenzquantifiziert, d.h. das Prädikat gilt für irgendeinenZustandρi(aber für alleσ).
ISchwächsteVorbedingungund stärksteNachbedingung:
IErgibt sich aus den Hoare-Regeln.
IErfordert durchgängige und agressiveVereinfachung.
Korrekte Software 41 [42]
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:
IZustände werdensehr groß
IRückwärtsrechnung erzeugt schnell sehr große „unbestimmte“ Zustände, die nicht vereinfacht werden können
IHier ist Vorwärtsrechnung vorteilhaft
Korrekte Software 42 [42]