all p-uses- ¨ UberdeckungstestIm all p-uses- ¨Uberdeckungstest wird gefordert, dass f¨ur jede Entscheidung und f¨ur jede darin verwendete Variable jede Kombination mit deren Definitionen
Trang 1all p-uses- ¨ Uberdeckungstest
Im all p-uses- ¨Uberdeckungstest wird gefordert, dass f¨ur jede Entscheidung und f¨ur jede darin verwendete Variable jede Kombination mit deren Definitionen, welche die Entscheidung erreichen, gepr¨uft wird Die Testf¨alle m¨ussen also das folgende
Krite-rium erf¨ullen: F¨ur jeden Knoten viim datenflussattributierten Kontrollflussgraph und
jeder Variablen x ∈ de f s(v i ) muss mindestens ein definitionsfreier Pfad bez¨uglich x von Knoten vi zu jeder Kante in dpu(x, vi) getestet werden.
Beispiel 7.2.20 Betrachtet wird das Programm aus Beispiel 7.2.16 Um 100% all p-uses- ¨Uberdeckung zu erzielen, sind zwei Testfalleingaben notwendig:(v in ,v1,v3, vout ) und (v in ,v1,v2,v3,v out ) Damit werden die beiden Kanten (v1,v3) und (v1,v2),
die mit p-uses attributiert sind, getestet.
Somit subsumiert der all p-uses- ¨Uberdeckungstest den Zweig¨uberdeckungstest
all c-uses- ¨ Uberdeckungstest
Analog zum all p-uses- ¨ Uberdeckungstest wird im all c-uses- ¨Uberdeckungstest ge-fordert, dass f¨ur jeden globalen berechnenden Zugriff und f¨ur jede darin verwendete Variable jede Kombination mit deren Definitionen, die den Zugriff erreichen, gepr¨uft wird Die Testf¨alle m¨ussen somit das folgende Kriterium erf¨ullen: F¨ur jeden Knoten
vi im datenflussattributierten Kontrollflussgraph und jeder Variablen x ∈ de f s(v i)
muss mindestens ein definitionsfreier Pfad bez¨uglich x von Knoten v izu jedem
Kno-ten in dcu(x, vi) getestet werden.
Beispiel 7.2.21 F¨ur das Programm aus Beispiel 7.2.16 f¨uhrt die Testfalleingabe (v in ,v1,v2,v3,v out ) zu einer 100%-igen all c-uses- ¨Uberdeckung.
Der all c-uses- ¨Uberdeckungstest subsumiert weder Zweig-, Anweisungs- noch
einen anderen defs/uses- ¨Uberdeckungstest
all c-uses/some p-uses- ¨ Uberdeckungstest
Der all c-uses- ¨Uberdeckungstest pr¨uft offensichtlich lediglich Variablendefinitionen, die in berechnenden Zugriffen m¨unden Variablen, die ausschließlich pr¨adikativ
ver-wendet werden, werden somit nicht getestet Der all c-uses/some p-uses- ¨
Uberde-ckungstest erweitert den all c-uses- ¨Uberdeckungstest dahingehend, dass f¨ur aus-schließlich pr¨adikativ verwendete Variablen ebenfalls Testf¨alle gefordert werden Somit m¨ussen die Testf¨alle das folgende Kriterium erf¨ullen:
• F¨ur jeden Knoten v iim datenflussattributierten Kontrollflussgraph und jeder
Va-riablen x ∈ de f s(v i ) muss mindestens ein definitionsfreier Pfad bez¨uglich x von Knoten vi zu jedem Knoten in dcu(x, vi) getestet werden.
• Ist dcu(x, v i) leer, so muss mindestens ein definitionsfreier Pfad bez¨uglich x von Knoten vi zu einer Kante in dpu(x, vi) getestet werden.
Trang 2Beispiel 7.2.22 F¨ur das Programm aus Beispiel 7.2.16 fordert der all c-uses/some p-uses- ¨Uberdeckungstest die Testfalleingabe (v in ,v1,v2,v3,v out) Die Definitionen in
vin und v2 erfordern den Test der berechnenden Zugriffe in v2und vout Da damit
bereits alle definierten Variablen getestet wurden, m¨ussen keine weiteren Testf¨alle hinzugenommen werden, obwohl der Zweig(v1,v3) noch nicht getestet wurde
Der all c-uses/some p-uses- ¨ Uberdeckungstest subsumiert den all defs- ¨ Uberde-ckungstest Er subsumiert aber weder den Zweig- noch den Anweisungs¨uberde-ckungstest
all p-uses/some c-uses- ¨ Uberdeckungstest
Analog zum all c-uses/some p-uses- ¨ Uberdeckungstest existiert der all p-uses/some c-uses- ¨ Uberdeckungstest Bei diesem wird zus¨atzlich zu den Testf¨allen des all
p-uses-¨
Uberdeckungstests gefordert, dass f¨ur eine Variable, die ausschließlich berechnend verwendet wird, also in keiner pr¨adikativen Benutzung auftaucht, weitere Testf¨alle generiert werden m¨ussen Das Kriterium f¨ur die Testf¨alle lautet somit:
• F¨ur jeden Knoten v iim datenflussattributierten Kontrollflussgraph und jeder
Va-riablen x ∈ de f s(v i ) muss mindestens ein definitionsfreier Pfad bez¨uglich x von Knoten vi zu jeder Kante in dpu(x, vi) getestet werden.
• Ist dpu(x, v i) leer, so muss mindestens ein definitionsfreier Pfad bez¨uglich x von Knoten vi zu einem Knoten in dcu(x, vi) getestet werden.
Beispiel 7.2.23 Betrachtet wird das Programm aus Beispiel 7.2.16 auf Seite 411 F¨ur eine 100%-ige all p-uses/some c-uses- ¨Uberdeckung sind die beiden Testfalleingaben
(v in ,v1,v3,v out ) und (v in ,v1,v2,v3,v out) notwendig Die Definitionen von min und
max in v inerfordern den Test der pr¨adikativen Verwendung in(v1,v3) und (v1,v2)
Zus¨atzlich wird aber durch die Definitionen in Knoten v2gefordert, dass der
berech-nende Zugriff in vout getestet wird Dies ist allerdings bereits im zweiten Testfall enthalten
Der all p-uses/some c-uses- ¨Uberdeckungstest subsumiert Zweig,
Anweisungs-und all p-uses- ¨Uberdeckungstest
all uses- ¨ Uberdeckungstest
Die Kombination aus den all c-uses/some p-uses- und all p-uses/some c-uses- ¨
Uber-deckungstests f¨uhrt zu dem all uses- ¨Uberdeckungstest Es wird dabei gefordert, dass f¨ur jede globale Definition jede erreichbare berechnende und pr¨adikative
Verwen-dung getestet wird Das Kriterium f¨ur die Testf¨alle lautet somit: F¨ur jeden Knoten vi
im datenflussattributierten Kontrollflussgraph und jeder Variablen x ∈ de f s(v i) muss
mindestens ein definitionsfreier Pfad bez¨uglich x von Knoten vi zu jedem Knoten
in dpu(x, vi) und zu jeder Kante in dpu(x, vi) getestet werden Der all uses- ¨
Uber-deckungstest subsumiert somit den all c-uses/some p-uses- und den all p-uses/some c-uses- ¨Uberdeckungstest
Die Subsumierungsrelationen der in diesem Abschnitt vorgestellten Verfahren zur Generierung strukturorientierter Testf¨alle ist zusammenfassend in Abb 7.20 dar-gestellt
Trang 3Mehrfach-
Bedingungs-¨uberdeckungstest Bedingungs-minimaler
Mehrfach-¨uberdeckungstest
Bedingungs-/
Entscheidungs-¨uberdeckungstest Bedingungs-einfacher
¨uberdeckungstest
Anweisungs-¨uberdeckungstest
Zweig-¨ Uberdeckungstest
all
p-uses-¨ Uberdeckungstest
all
defs-¨
Uberdeckungstest
all
c-uses-¨ Uberdeckungstest
all p-uses/
some
c-uses-¨ Uberdeckungstest
all c-uses/
some
p-uses-¨ Uberdeckungstest
all
uses-strukturierter
Pfad-¨uberdeckungstest
Pfad-¨uberdeckungstest
Abb 7.20 Subsumierungsrelation zwischen den Verfahren zur Generierung
strukturorientier-ter Testf¨alle
7.3 Formale funktionale Eigenschaftspr ¨ufung von Programmen
Die automatischen Verfahren zur formalen funktionalen Eigenschaftspr¨ufung von Programmen haben in den vergangenen Jahren enorme Fortschritte verzeichnet Einen guten ¨Uberblick hier¨uber gibt die Ver¨offentlichung [140] Im Folgenden wer-den in Anlehnung an [140] einige Techniken n¨aher betrachtet
7.3.1 Statische Programmanalyse
Der Begriff statische Programmanalyse beschreibt Techniken, mit deren Hilfe
Infor-mationen ¨uber das Verhalten von Programmen ermittelt werden k¨onnen, ohne diese auszuf¨uhren Viele dieser Techniken wurden f¨ur die Optimierungsphase in Com-pilern konzipiert Dennoch ist deren Anwendungsgebiet nicht auf diese Aufgabe beschr¨ankt Hier wird statische Programmanalyse im Kontext der formalen Eigen-schaftspr¨ufung von Programmen betrachtet
Ein grundlegendes Problem in der Programmverifikation ist, dass viele Verifika-tionsfragen unentscheidbar oder zu rechenintensiv sind, um sie zu beantworten Des-halb berechnen Techniken zur statischen Programmanalyse typischerweise lediglich Approximationen f¨ur Eigenschaften Diese m¨ussen allerdings Korrektheitsgarantien liefern, d h nicht zu Fehlschl¨ussen verleiten
Trang 4Beispiel 7.3.1 Ein statisches Verfahren zur Detektion von
”Division durch Null“-Fehlern in einem gegeben Programm muss s¨amtliche Werte eines Divisors, die zur Laufzeit des Programms auftreten k¨onnen, ber¨ucksichtigen Da eine Aufz¨ahlung al-ler potentiellen Werte in der Regel aus Zeitgr¨unden nicht m¨oglich ist, arbeiten Ver-fahren zur statischen Programmanalyse typischerweise mit Teil- bzw Obermengen
Verwendet die Analyse eine Teilmenge aller m¨oglichen Werte und findet dabei keine
Fehler, kann keine endg¨ultige Aussage ¨uber die Abwesenheit von
”Division durch Null“-Fehlern gemacht werden Liefert das Analyseverfahren dennoch dieses Ergeb-nis, so kann diese Aussage falsch sein, da die verwendet Approximation inkorrekt ist
Verwendet das Verfahren hingegen eine Obermenge aller m¨oglichen Werte eines
Divisors, so ist die Approximation korrekt, und die Aussage, dass keine
”Division durch Null“-Fehlern existieren, gerechtfertigt Allerdings kann eine solche ¨
Uberap-proximation zu falschnegativen Ergebnissen f¨uhren, d h der Fehler tritt lediglich
unter Verwendung von Werten auf, die zwar in der Obermenge, nicht aber in der ur-spr¨unglichen Menge m¨oglicher Werte des Divisors liegt In diesem Zusammenhang
spricht man auch von unzul¨assigen Gegenbeispielen.
Im Gegensatz zu falschnegativen Ergebnissen k¨onnen bei der statischen Pro-grammanalyse auch falschpositive Ergebnisse auftreten Hierbei handelt es sich um Testf¨alle, die als fehlerfrei angesehen werden, es aber in Wirklichkeit gar nicht sind Aufgrund der Unentscheidbarkeit statischer Analyseprobleme kann nicht garantiert werden, dass eine Methode sowohl keine falschnegativen als auch keine falschposi-tiven Ergebnisse erzeugt
Statische Programmanalyse beruht auf der Idee der Fixpunktberechnung (siehe auch Anhang C.4) Dabei werden Wertemengen solange durch ein Programm pro-pagiert und angepasst, bis diese Mengen sich nicht weiter ¨andern Dies wird anhand des Beispiels aus [140] illustriert:
Beispiel 7.3.2 Gegeben ist folgender Ausschnitt eines C-Programms:
5 } while (i < 5);
Es sollen nun alle Werte, welche die Variable i annehmen kann, ermittelt werden Dies ist beispielsweise sinnvoll, wenn i als Index f¨ur Arrays verwendet wird und ein Zugriff außerhalb des deklarierten Array-Bereichs verhindert werden soll Der Kontroll-Datenflussgraph zu dem obigen Programmsegment ist in Abb 7.21 zu
se-hen Der Zustand v2repr¨asentiert dabei die Programmzeilen 2 und 3 Der Zustand v5
repr¨asentiert das Verlassen des Programmabschnitts und der Zustand veden Fehler-zustand, der durch die assert-Anweisung erreicht wird
Links in Abb 7.21 sind f¨ur die ersten beiden Iterationen f¨ur jeden Knoten des Kontrollflussgraphen die zugeh¨orige Wertemenge f¨ur die Variable i angegeben
Die-se enth¨alt diejenigen Werte, welche die Variable i bei Erreichen des repr¨aDie-sentierten
Trang 5i < 5
i > 10
1 Iteration 2 Iteration
NOP
NOP
NOP
NOP
{0}
{0}
INT
{2}
{0,2}
{0,2}
{2,4}
i = 0;
i = i + 2;
Abb 7.21 Kontroll-Datenflussgraph zu dem Programmsegment aus Beispiel 7.3.2
Zustands tragen kann Zu Beginn der ersten Iteration im Zustand v1h¨alt die Varia-ble i einen beliebigen Wert Die Wertemenge ist somit die Menge aller Werte in INT, die eine Variable von Typ int in der Programmiersprache C annehmen kann F¨ur die statische Programmanalyse werden nun die Wertemengen entlang der Kon-trollflusskanten propagiert und entsprechend der Operationen im Datenflussgraphen manipuliert
Die beiden ersten Iterationen laufen wie folgt ab:
1 Zu Beginn ist die Variable i nicht initialisiert und nimmt somit einen
beliebi-gen Wert aus der Menge INT an Bei Erreichen von Zustand v2wurde i bereits initialisiert und besitzt den Wert 0 Somit ergibt sich die Wertemenge{0} mit
lediglich einem Element Die assert-Anweisung in Zeile 3 ¨andert an dieser
Wertebelegung nichts Bei Erreichen von Zustand v4wurde die Variable i be-reits um 2 erh¨oht, weshalb die Wertemenge als einziges Element die 2 enth¨alt
Zustand v5und vewerden in der ersten Iteration aufgrund der Kontrollanweisun-gen 2< 5 bzw 0 ≤ 10 nicht erreicht.
2 Die Wertemenge{2} wird nun von Zustand v4zu Zustand v2propagiert Da v2
mehrere Eingangskanten besitzt, kann sich in diesem Knoten die Wertemenge vergr¨oßern, da die Vereinigung aller ankommenden Wertemengen gebildet wer-den muss Das Ergebnis ist somit die Wertemenge{0,2}, wobei das Element 0
noch aus der ersten Iteration stammt Da beide Werte kleiner gleich zehn sind,
wird die Wertemenge nicht an Zustand ve propagiert Man beachte aber auch,
dass der Knoten v in diesem Durchlauf nicht wieder betrachtet werden muss,
Trang 6da sich die dort ermittelte Wertemenge nicht ge¨andert hat Die Menge {0,2} wird nun unver¨andert weiter an Knoten v3propagiert Dort werden die Elemente
um zwei erh¨oht, weshalb sich f¨ur Zustand v4die Wertemenge{2,4} ergibt Da beide Elemente echt kleiner f¨unf sind, wird die Wertemenge nicht an v5jedoch
aber an v2propagiert
Die Iteration wird solange fortgesetzt, bis ein Fixpunkt erreicht ist, d h keine ¨ Ande-rungen in den Wertemengen auftreten
Die eben gerade beschriebene Programmanalyse wird als konkrete Interpretation
bezeichnet Dies liegt darin begr¨undet, dass Elemente aus INT und beliebigen
Teil-mengen daraus konkrete Werte und somit einen konkreten Wertebereich darstellen Abstrakte Interpretation
Konkrete Interpretation l¨asst sich in der Praxis nicht anwenden, da die Wertemen-gen schnell anwachsen Bereits 1965 stellte Peter Naur fest, dass es ausreichend sein kann, abstrakte Werte bei der Programmanalyse zu verwenden [341] Basierend auf
diesem Ergebnis entwickelten Cousot und Cousot 1977 die Methode der abstrak-ten Interpretation [118] Abstrakte Interpretation bedient sich zweier zentraler Kon-zepte: dem sog abstrakten Wertebereich, der eine Approximation eines konkreten Wertebereichs ist, und sog abstrakter Funktionen, die dazu dienen, konkrete Werte
in abstrakte Werte zu ¨ubersetzen Abstrakte Interpretation hat zum Ziel, eine appro-ximative L¨osung des Programmanalyseproblems zu liefern Dabei wird das Verhal-ten eines Programms f¨ur abstrakte Wertebereiche analysiert Dies geschieht, indem die Operationen auf den konkreten Wertebereichen aus der konkreten Interpretation durch geeignete Funktionen ersetzt werden
Abstrakte Wertebereiche lassen sich in relationale und nichtrelationale
abstrak-te Werabstrak-tebereiche einabstrak-teilen Beispiele f¨ur nichtrelationale Werabstrak-tebereiche sind Vor-zeichen-Wertebereiche, Intervall-Wertebereiche oder Kongruenz-Wertebereiche Der
Vorzeichen-Wertebereich besitzt drei Elemente{pos,neg,zero} zur Unterscheidung
positiver und negativer Zahlen, sowie der Null Intervall-Wertebereiche sind expres-siver, da der Vorzeichen-Wertebereich durch{[−∞,0),[0,0],(0,∞]} repr¨asentiert
werden kann
Beispiel 7.3.3 Betrachtet wird wiederum das Programmsegment aus Beispiel 7.3.2
mit dem Kontroll-Datenflussgraphen aus Abb 7.21 Ein m¨oglicher abstrakter Werte-bereich ist z B die Menge der Intervalle{[a,b] | a ≤ b∧a,b ∈ Z} Die in der
konkre-ten Interpretation verwendekonkre-ten Operationen Addition und Vereinigung m¨ussen f¨ur die abstrakte Interpretation ersetzt werden durch Addition und Vereinigung von In-tervallen Die abstrakte Interpretation ist in Abb 7.22 an dem Beispiel durchgef¨uhrt
Im Folgenden seien min bzw max der minimale bzw maximale Wert, der sich
im Wertebereich INT darstellen l¨asst In Zustand v1, zu Beginn der ersten Iteration, ist die Variable i noch nicht initialisiert und kann somit einen beliebigen Wert im Intervall[min,max] annehmen Nach der Initialisierung (Zustand v ) besitzt i den
Trang 7i ≤10
i < 5
i > 10
1 Iteration 2 Iteration 3 + 4 Iteration
i ≥5
NOP
NOP
NOP
NOP
v5
v1
i = 0;
i = i + 2;
v2
v3
v4
v e
[min,max]
[0,0]
[0,0]
[2,2]
[0,2]
[0,2]
[2,4]
[0,4]
[0,4]
[2,6]
Abb 7.22 Abstrakte Interpretation mit Intervallen
konkreten Wert 0, was als Intervall[0,0] geschrieben wird Bis auf die
Intervall-schreibweise der Wertemengen verl¨auft die erste Iteration der abstrakten Interpre-tation ¨aquivalent zur konkreten InterpreInterpre-tation aus Beispiel 7.3.2 Man beachte aber, dass Zuweisung und Addition sich jeweils auf Unter- und Obergrenze des Intervalls auswirkt Nach Beendigung der ersten Iteration wird das Intervall[2,2] von Zustand
v4an Zustand v2propagiert Zusammen mit dem Intervall[0,0] aus der
Initialisie-rung von i ergibt sich eine ¨Uberapproximation des Wertebereichs durch das Intervall
[0,2] Man sieht also, dass die Mengenvereinigung in der Intervallarithmetik durch
die Minimums- bzw Maximumsoperation ¨uber die Bereichsgrenzen ersetzt wurde
Bei Erreichen von Zustand v4in der zweiten Iteration wird die Wertemenge mit dem Intervall[2,4] approximiert.
Zu Beginn der dritten Iteration ergibt sich somit die Wertemenge f¨ur v2 von
[min{0,2},max{0,4}] = [0,4] Die Wertemenge f¨ur v4wird in dieser Iteration mit
[2,6] approximiert In diesem Fall ist die Obergrenze erstmals gr¨oßer als die
Schran-ke 5, die zur Steuerung der while-Schleife verwendet wird Aus diesem Grund muss die Wertemenge geteilt werden, um eine Fallunterscheidung zu erreichen Die appro-ximierte Wertemenge[2,4] wird zur¨uck an v2propagiert, w¨ahrend das verbleibende Intervall[5,6] an Zustand v5¨ubertragen wird Nach dieser Aufteilung der
Wertemen-ge ist das an v2propagierte Intervall aber das selbe, das auch am Ende von Iteration zwei propagiert wurde Eine vierte Iteration offenbart somit den Fixpunkt in der ab-strakten Interpretation
Trang 8Da es sich bei der Intervallbildung um eine ¨Uberapproximation handelt, kann man auch f¨ur jede konkrete Programmausf¨uhrung schließen, dass die Zusicherung assert(x <= 10) immer g¨ultig ist
Kongruenz-Wertebereiche repr¨asentieren den Wert value (x) einer Variablen x als (value(x) mod k) f¨ur ein gegebenes k F¨ur k = 2 erh¨alt man den sog Parit¨atswertebe-reich {odd,even} Man beachte, dass der Intervall-Wertebereich zwar deutlich mehr
Elemente enthalten kann, aber dennoch nicht expressiver ist als der Parit¨atswerte-bereich, da die geraden und ungeraden Zahlen nicht durch eine endliche Anzahl
an Intervallen repr¨asentiert werden k¨onnen Das folgende Beispiel zu Kongruenz-Wertebereichen stammt aus [140]
Beispiel 7.3.4 Betrachtet wird der Ausdruck 1 /(x − y) Kann unter Verwendung der
abstrakten Interpretation mit Kongruenz-Wertebereichen f¨ur ein gegebenes, aber
be-liebiges k gezeigt werden, dass (x mod k) = (y mod k) ist, so kann daraus geschlossen
werden, dass eine Division durch Null in dieser Anweisung nicht auftreten kann Nicht relationale abstrakte Wertebereiche lassen sich leicht handhaben
Aller-dings k¨onnen mit ihnen bereits Zusicherungen der Form x ≤ y nicht mehr ¨uberpr¨uft werden Relationale abstrakte Wertebereiche l¨osen dieses Problem Eine einfache Form relationaler abstrakter Wertebereiche sind die sog differenzenbeschr¨ankten Matrizen (engl difference bound matrices, DBMs) Diese bestehen aus Konjunk-tionen von Ungleichungen der Form x −y ≤ c Obwohl DBM-Wertebereiche
expres-siver als Intervall-Wertebereiche sind besteht dennoch eine Einschr¨ankung in der Form, dass Beschr¨ankungen der Art−x − y ≤ c nicht ausgedr¨uckt werden k¨onnen.
Oktagon-Wertebereiche beseitigen diese Einschr¨ankung, indem sie Beschr¨ankungen
der Form ax + by ≤ c erlauben, wobei a,b ∈ {−1,0,1} sind Eine Erweiterung
neh-men schließlich Oktaeder-Wertebereiche durch Verallgemeinerung auf mehr als zwei Variablen vor
Eine der ersten relationalen abstrakten Wertebereiche sind
Polyeder-Wertebe-reiche Diese werden durch die Konjunktion von Ungleichungen der Form a1x1+
a2x2+ ··· + a nxn ≤ c beschrieben, wobei a1, ,a n ,c ∈ Z sind Die Manipulation
von Polyeder-Wertebereichen ist allerdings nicht trivial und bedarf der Berechnung
sog konvexer H¨ullen Die Komplexit¨at dieser Berechnungen ist exponentiell in der
Anzahl der Variablen
Die Expressivit¨at eines Wertebereichs entscheidet dar¨uber, welche funktionalen Eigenschaften mit abstrakter Interpretation gezeigt werden k¨onnen Einige von den oben genannten abstrakten Wertebereichen lassen sich aber nicht hinsichtlich ih-rer Expressivit¨at vergleichen Hier sei nochmals das Beispiel des Parit¨atswertebe-reichs und des Intervall-WertebeParit¨atswertebe-reichs genannt Die Vorzeichen-, Intervall-, DBM-, Oktagon-, Oktaeder- und Polyeder-Wertebereiche bilden eine Hierarchie Obwohl Polyeder-Wertebereiche die Expressivsten in dieser Hierarchie sind, reichen diese nicht aus, um Eigenschaften ¨uber Ungleichheiten zu zeigen
Beispiel 7.3.5 Gegeben ist der Ausdruck 1 /(2·x+1−y) [140] Um mittels
abstrak-ter Inabstrak-terpretation zu zeigen, dass keine Division durch Null in dieser Anweisung auf-treten kann, muss ein abstrakter Wertebereich gew¨ahlt werden, in dem 2· x + 1 = y
Trang 9gezeigt werden kann Dies ist nicht mit den oben beschriebenen relationalen
abstrak-ten Wertebereichen m¨oglich Der abstrakte Wertebereich der linearen Kongruenzen
verbindet Polyeder-Wertebereiche mit Kongruenz-Wertebereichen Diese enthalten
auch Gleichungen der Form a1x1+ ··· + a nxn = c mod k f¨ur ein gegebenes k Damit
kann gezeigt werden, dass(2 · x + 1) mod k ungleich y mod k ist, was auch die Frage
nach einer m¨oglichen Division durch Null beantwortet
7.3.2 SAT-basierte Modellpr ¨ufung von C-Programmen
F¨ur die SAT-basierte Modellpr¨ufung (siehe Abschnitt 5.3.2) wird, neben der zu pr¨ufenden Eigenschaft, ein Modell des Programms ben¨otigt Dieses muss ein end-licher Automat sein, der aus Zust¨anden und Zustands¨uberg¨angen besteht In einem Programm fasst ein Zustand den Wert des Programmz¨ahlers, die Werte der Pro-grammvariablen und den Zustand des Speichers zusammen Zustands¨uberg¨ange be-schreiben m¨ogliche ¨Anderungen bei der Programmausf¨uhrung von einem Zustand zum n¨achsten
Da der Kontrollfluss lediglich am Ende eines Grundblocks verzweigen und am Anfang eines Grundblocks eintreten kann, kann es sinnvoll sein, anstatt jede An-weisung einzeln zu codieren, eine Codierung auf Grundbl¨ocken vorzunehmen Ein solches Verfahren ist in [242] beschrieben
Beispiel 7.3.6 Gegeben ist das folgende C-Programm [242]:
10
Der resultierende Kontroll-Datenflussgraph ist in Abb 7.23 zu sehen Man erkennt,
dass jeder Zustand viim Kontrollflussgraphen einem Grundblock im Programm ent-spricht Außerdem ist gezeigt, wie Parameter im Falle nichtrekursiver Funktions-aufrufe ¨ubergeben werden Dabei werden Argumente in der Variable l ¨ubergeben
Trang 10und mittels der Variablen r wird unterschieden, an welche Variable das Ergebnis zu
¨ubertragen ist
NOP
NOP
NOP
NOP
NOP
NOP NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
x ≤ 4
x > 4
r= 1
r= 0
t ≤ 6
t > 6
NOP
NOP
NOP
NOP
y = t;
l = y;
t -= 3;
t ;
x = t;
r = 1;
v3
v5
v4
v1
v2
t = l + 2;
v11
v10
v9
v7 v8
y++;
v6
Abb 7.23 Kontroll-Datenflussgraph f¨ur das Programm aus Beispiel 7.3.6
Jedem Grundblock i (Zustand im Kontrollflussgraphen) wird nun eine
einzel-ne bin¨are Variable bi ∈ B zugeordnet, die anzeigt, ob der Kontrollfluss gerade in diesem Grundblock liegt Die Belegung der Variablen bi kann direkt aus dem
Pro-grammz¨ahler abgeleitet werden Man beachte, dass bi = T impliziert, dass ∀ j =i b j=
F ist
Nach der Konstruktion des Kontroll-Datenflussgraphen werden zun¨achst die Da-tenflussgraphen zu jedem Basisblock einzeln in Booleschen Formeln codiert Dabei wird f¨ur jede Zuweisung var = expr eine kombinatorische Schaltung f¨ur expr