Seminar Werkzeuggestütze Softwareprüfung

Werbung
Seminar Werkzeuggestütze
Softwareprüfung
Slicing
Sebastian Meyer
Überblick
• Einführung und Begriffe
• Static Slicing
• Dynamic Slicing
• Erweiterte Slicing-Techniken
• Fazit
Sebastian Meyer: Slicing
2
Was ist Slicing? (I)
• Program slicing is a method for automatically
decomposing programs by analyzing their data
flow and control flow.
• Starting from a subset of a program’s behavior,
slicing reduces that program to a minimal form
which still produces that behavior.
• The reduced program, called a „slice“, is an
independent program guaranteed to represent
faithfully the original program within the domain of
the specified subset of behavior.
Mark Weiser, 1979
Sebastian Meyer: Slicing
3
Was ist Slicing? (II)
• Slicing wurde 1979 erstmals von Weiser
definiert.
– Mark Weiser, Program slices, formals,
psychological and practical investigation of an
automatic program abstraction method. PhD
thesis, University of Michigan, Ann Arbor,
1979.
• Slicing beantwortet allgemein die Frage „welche
Anweisung beeinflusst die Berechnung einer
anderen Anweisung“
Sebastian Meyer: Slicing
4
Beispiel
1: int OddNumsSum(int n)
2: {
3: int i = 0;
4: int sum = 0;
5: while (i <= n)
6: {
7:
if (i % 2 == 1)
8:
sum++;
9:
i++;
10: }
11: return sum;
12: }
Sebastian Meyer: Slicing
5
Begriffe (I)
• Slice
– Ein Slice ist eine Menge von Anweisungen, eines
Programms P, die eine Variable v an einem
bestimmten Programmpunkt s beeinflussen oder
von ihr beeinflusst werden.
• Slicing
– Slicing ist der Vorgang des Berechnens eines
Slice.
Sebastian Meyer: Slicing
6
Begriffe (II)
• Slicing-Kriterium
– Das Tupel aus Variable v und deren
Programmpunkt s wird Slicing-Kriterium (v,s)
genannt
• Startkonfiguration
– Die Menge der Werte aller Parameter eines
Programms, welche beim Programmaufruf
übergeben bzw. während des Programmablaufs
eingelesen werden können.
Sebastian Meyer: Slicing
7
Beispiel zu den Begriffen
1: int OddNumsSum(int n)
int OddNumsSum(int n)
2: {
{
3:
int i = 0;
int i = 0;
4:
int sum = 0;
while (i <= n)
5:
while (i <= n)
{
Slicing
6:
{
i++;
7:
if (i % 2 == 1)
}
8:
sum++;
}
9:
i++;
Slice
10:
}
(i,9)
n=6
11:
return sum;
12: }
Slicing-Kriterium
Start-Konfiguration
Programm
Sebastian Meyer: Slicing
8
Arten von Slicing (I)
• Static Slicing
– Die Analyse erfolgt unabhängig von einer
bestimmten Startkonfiguration
• (Exact) Dynamic Slicing
– Die Analyse erfolgt abhängig von einer
bestimmten Startkonfiguration
Sebastian Meyer: Slicing
9
Arten von Slicing (II)
• Backward Slicing
– Beinhaltet alle Anweisungen, die die
Variable des Slicing-Kriteriums beeinflussen
können.
• Forward Slicing
– Beinhaltet alle Anweisungen, die von der
Variable des Slicing-Kriteriums beeinflusst
werden.
Sebastian Meyer: Slicing
10
Einsatzzwecke von Slicing
• Debuggen
• Testen
• Zusammenfügen zweier Programme
• Software Wartung
• Compilerbau
Sebastian Meyer: Slicing
11
Static Slicing (I)
• Die Analyse erfolgt unabhängig von einer
bestimmten Startkonfiguration.
• Berechnung des Control flow graphs (CFG)
Sebastian Meyer: Slicing
12
Control flow graph (I)
• Ein CFG ist ein gerichteter Graph
– Die Knoten repräsentieren die Anweisungen des
Programms
– Die Kanten repräsentieren den Kontrollfluss des
Programms
• Zu jedem Knoten kann notiert werden, welche Variablen
definiert oder geschrieben werden (def) und welche
Variablen gelesen werden (ref).
• Bei Verzweigungen wird jede ausgehende Kante mit
einem eindeutigen Label beschriftet.
Sebastian Meyer: Slicing
13
Control flow graph (II)
START
int i = 0;
def = {i}
int sum = 0;
while (i <= n )
def = {sum}
ref = {i,n}
true
if (i % 2 == 1)
false
true
ref = {i}
sum++;
false
def = {sum}
i++;
def = {i}
return sum;
ref = {sum}
EXIT
Sebastian Meyer: Slicing
14
Static Slicing (II)
• Die Analyse erfolgt unabhängig von einer
bestimmten Startkonfiguration.
• Berechnung des Control flow graphs (CFG)
• Berechnung des Program dependence graph (PDG)
Sebastian Meyer: Slicing
15
Program dependence graph (I)
• Besteht aus dem Data dependence graph
– Ein gerichteter Graph G, dessen Knoten N die
Anweisungen des Programms enthalten.
– Die Kanten K geben die Abhängigkeit der
Variablenbenutzung an
• Berechnungsvorschrift:
1. ∃ Weg p von n nach m im CFG (n →* m)
2. ∃ Variable v, mit v ∈ def(n) und v ∈ ref(m)
3. ∀ Knoten k ≠ n im Pfad p gilt: v ∉ def(k)
Sebastian Meyer: Slicing
16
Program dependence graph (II)
int i = 0;
int sum = 0;
while (i <= n )
if (i % 2 == 1)
return sum;
i++;
sum++;
Sebastian Meyer: Slicing
17
Program dependence graph (III)
• Besteht aus dem Control dependence graph
– Ein gerichteter Graph G, dessen Knoten N die
Anweisungen des Programms plus den
Startpunkt enthalten.
– Die Kanten geben die Abhängigkeiten der
Anweisungen untereinander an.
Sebastian Meyer: Slicing
18
Program dependence graph (IV)
• Control dependence graph: Berechnung
– Erweitern des CFG um eine Kante von Start zu
Stop
– Berechnung der Post-Dominatoren
– Berechnung des CDG
1. ∃ Pfad p von n nach m im CFG (n →* m)
2. m ist ein Post-Dominator für jeden Knoten in p, außer
für n
3. m ist kein Post-Dominator für n.
Sebastian Meyer: Slicing
19
Program dependence graph (V)
Sebastian Meyer: Slicing
20
Program dependence graph (VI)
• Das Zusammenfügen des Control und des Data dependence
graphs ergibt den Program dependence graph.
Sebastian Meyer: Slicing
21
Static Slicing (III)
• Die Analyse erfolgt unabhängig von einer
bestimmten Startkonfiguration.
• Berechnung des Control flow graphs (CFG)
• Berechnung des Program dependence graph (PDG)
• Berechnung des static slice aus dem PDG
Sebastian Meyer: Slicing
22
Static Slicing (IV)
• Nach Berechnung des PDG lässt sich aus diesem ein static
slice berechnen.
• Ein backward slice S(n) über den PDG am Knoten n besteht
aus allen Knoten m, von denen n (transitiv) abhängt:
S(n) = {m | m →* n}
• Ein forward slice SF(n) über den PDG am Knoten n besteht
aus allen Knoten m, die (transitiv) von n abhängen:
SF(n) = {m | n → * m}
• n ist dann das Slicing-Kriterium.
Sebastian Meyer: Slicing
23
Static Slicing (V)
1: int OddNumsSum(int n)
2: {
3:
int i = 0;
4:
5:
while (i <= n)
6:
{
7:
8:
9:
i++;
10:
}
11:
12: }
Static Backward Slice für (i,8)
1: int OddNumsSum(int n)
2: {
3:
4:
5:
while (i <= n)
6:
{
7:
if (i % 2 == 1)
8:
sum++;
9:
i++;
10:
}
11:
return sum;
12: }
Static Forward Slice für (i,8)
Sebastian Meyer: Slicing
24
Fortgeschrittenes Static Slicing
• Beachtung von Nebeneffekten bei Strukturen/Arrays
• Pointer-Arithmetik
• Slicing über mehrere Prozeduren
• Slicing von Vererbungen
• Slicing von Nebenläufigen Programmen
Sebastian Meyer: Slicing
25
Fazit Static Slicing
• Aufwand hängt im wesentlichen von der Anzahl der
verwendeten Variablen und den Knoten und Kanten im CFG
ab.
• Die Überführung in einen PDC kann leicht mittels
syntaktischer Analyse vorgenommen werden.
– Dies ist ein Vorteil bei der Berechnung von mehreren
Slices
• Die Berechnung eines static backward slices kann immer in
endlich vielen Schritten vorgenommen werden.
• Static Slicing liefert eine Abschätzung nach oben.
Sebastian Meyer: Slicing
26
Dynamic Slicing
• Zusätzlich zum Slicing-Kriterium muss auch noch
Startkonfiguration berücksichtigt werden.
– Abhängig von der Startkonfiguration kann für ein Kriterium
verschiedene Slices berechnet werden
• Es muss eine semantische Analyse vorgenommen werden
um einen vollständigen Program-Execution-Trace zu erhalten
– Probleme bei Endlosschleifen
• Aus dem Programm und dem Program-Execution-Trace kann
für die spezielle Startkonfiguration zu einem Slicing-Kriterium
der dynamic slice berechnet werden.
Sebastian Meyer: Slicing
27
Unterschiedliche Startkonfigurationen
1: int OddNumsSum(int n)
2: {
3:
int i = 0;
4:
int sum = 0;
5:
while (i <= n)
6:
{
7:
if (i % 2 == 1)
8:
9:
i++;
10:
}
11:
return sum;
12: }
Dynamic Backward Slice für
(sum, 10) und n=0
1: int OddNumsSum(int n)
2: {
3:
int i = 0;
4:
int sum = 0;
5:
while (i <= n)
6:
{
7:
if (i % 2 == 1)
8:
sum++;
9:
i++;
10:
}
11:
return sum;
12: }
Dynamic Backward Slice für
(sum, 10) und n=1
Sebastian Meyer: Slicing
28
Program execution trace
• Problem: Berechnung des PET
• Ideen:
– Ergänzung des Programms um Anweisungen zur
Erzeugung eines PET
– Interpretation des Quellcodes
• Bei Anweisungen mit Nebeneffekten kann es
aufgrund der schwierigen Berechnung zu
Ungenauigkeiten kommen.
Sebastian Meyer: Slicing
29
Fazit Dynamic Slicing
• Der Aufwand zur Berechnung des PET kann
schnell sehr gross werden.
• Durch die unbedingte Ausführung des
Programms kann der Aufwand so groß
werden, dass er in keinem Verhältnis zur
eingesetzten Zeit steht.
• Dynamic Slicing liefert eine Abschätzung nach
unten.
Sebastian Meyer: Slicing
30
Operationen auf Slices
• Schnitt zwischen zwei Slices
– Ergibt die gemeinsam genutzten
Anweisungen.
• Schnitt zwischen Forward und Backward
Slice
– Anweisungen, die eine Eingabe zu einer
Ausgabe transformiert.
Sebastian Meyer: Slicing
31
Approximate Dynamic Slicing
• Mischung aus Static Slicing und (Exact) Dynamic
Slicing
• Zunächst wird der PET gebildet
• Darauf wird ein Static Slice für das Slicing-Kriterium
berechnet
Sebastian Meyer: Slicing
32
Fazit
• Static slicing kann mit geringem Aufwand berechnet
werden, Slices sind jedoch nicht unbedingt minimal.
• Dynamic slicing liefert genauere Slices hat aber
teilweise einen unverhältnismäßigen
Berechnungsaufwand.
• Slicing ist immer noch Gegenstand aktueller
Forschung.
• Static Slicing ist Handwerkszeug des Compilerbaus.
Sebastian Meyer: Slicing
33
Herunterladen