16.01.2014 Aufrufe

6 Race Conditions

6 Race Conditions

6 Race Conditions

MEHR ANZEIGEN
WENIGER ANZEIGEN

Erfolgreiche ePaper selbst erstellen

Machen Sie aus Ihren PDF Publikationen ein blätterbares Flipbook mit unserer einzigartigen Google optimierten e-Paper Software.

208<br />

10 <strong>Race</strong> <strong>Conditions</strong><br />

onsmechanismen und alle gemeinsam benutzten Variablen modelliert und dazu<br />

speichert, ob diese lesend und/oder schreibend benutzt werden. In diesem Graphen<br />

werden dann alle möglichen Programmpfade eines Threads durchlaufen<br />

und auf Basis dieser Traversierung kommt ein dynamischer Algorithmus zum<br />

Einsatz, zum Beispiel Eraser. Klingt bis jetzt nicht so schwierig. Der Teufel steckt<br />

aber im Detail.<br />

Statische Werkzeuge haben speziell bei der Verwendung von Zeigern Probleme.<br />

Sie können dann nicht immer feststellen, ob eine Variable von zwei<br />

Threads gemeinsam verwendet wird und müssen sich dann auf Heuristiken stützen,<br />

die zum Beispiel versuchen, über den Typ zu ermitteln, ob die Dereferenzierung<br />

potenziell zur Laufzeit die gleiche Adresse betreffen kann. Semaphore können<br />

binär (als Locks) verwendet werden oder als Zähler mit einem potenziell von<br />

0 oder 1 verschiedenen Zählerstand. Auch da muss das Werkzeug eine Annahme<br />

treffen, die zum Beispiel nach bekannten Design-Mustern für die Verwendung als<br />

Zähler sucht. Eine weitere Problemstellung – und nicht die einzige – ist das<br />

Erkennen, wann Code parallel ausgeführt wird. Enthält der Code Zeiger auf<br />

Unterprogramme (Function Pointers), so kann es sehr schwer werden, festzustellen,<br />

in welchem Thread-Kontext eine Prozedur ausgeführt wird. Auch hier müssen<br />

dann wieder Heuristiken herhalten.<br />

Wegen der Notwendigkeit des Einsatzes von Heuristiken neigen statische<br />

Analysewerkzeuge zu deutlich mehr Falschwarnungen als dynamische Verfahren.<br />

Ein Großteil der Intelligenz von statischen Werkzeugen steckt daher in Mechanismen<br />

zur Ausfilterung und Priorisierung dieser Falschwarnungen.<br />

Andere statische Verfahren verwenden anstelle des Kontrollflussgraphen abstrakte<br />

Interpretation (siehe auch Kapitel 11 für ein weiteres Anwendungsbeispiel<br />

von abstrakter Interpretation), und es gibt auch Ansätze mit Model Checking<br />

und formalen Korrektheitsbeweisen. Es ist davon auszugehen, dass die formalen<br />

Methoden bei großen Anwendungen schwer durchführbar sind. Ein Werkzeug<br />

zur statischen Data-<strong>Race</strong>-Analyse in C ist zum Beispiel das gratis erhältliche<br />

LockLint, Teil von Oracle Solaris Studio.<br />

10.3.2 Vergleich zur dynamischen Data-<strong>Race</strong>-Analyse<br />

Im Gegensatz zu den dynamischen Verfahren ist es bei statischen Verfahren nicht<br />

notwendig, Testtreiber zu schreiben. Das ist von großem Vorteil, wenn man Systeme<br />

analysiert, für die es keine umfassenden Systemtests mit hoher struktureller<br />

Testabdeckung gibt oder wenn Testhardware nicht immer zur Hand ist. Der Test<br />

von Linux ist ein klassisches Beispiel: unzählige Hardware-Treiber. Für dynamische<br />

Tests müsste immer die jeweilige Hardware parat sein!<br />

Nachdem der Code zur Analyse nicht instrumentiert werden muss, spielen<br />

Platz- oder Laufzeitprobleme am Zielsystem keine Rolle. Die Ersparnis der<br />

Erstellung der Testtreiber wird aber teilweise durch den hohen Aufwand bei der

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!