Warum ist volatile
in C benötigt? Wofür wird es verwendet? Was wird es tun?
Antworten
Zu viele Anzeigen?Meiner Meinung nach sollten Sie nicht zu viel erwarten von volatile
. Zur Veranschaulichung sehen Sie sich das Beispiel in Nils Pipenbrinck's hoch bewertete Antwort .
Ich würde sagen, sein Beispiel ist nicht geeignet für volatile
. volatile
wird nur dazu verwendet: verhindern, dass der Compiler nützliche und wünschenswerte Optimierungen vornimmt . Es ist nichts über den Thread sicher, atomaren Zugriff oder sogar Speicher Ordnung.
In diesem Beispiel:
void SendCommand (volatile MyHardwareGadget * gadget, int command, int data)
{
// wait while the gadget is busy:
while (gadget->isbusy)
{
// do nothing here.
}
// set data first:
gadget->data = data;
// writing the command starts the action:
gadget->command = command;
}
die gadget->data = data
vor gadget->command = command
ist nur im kompilierten Code durch den Compiler gewährleistet. Zur Laufzeit ordnet der Prozessor die Daten und die Befehlszuweisung unter Berücksichtigung der Prozessorarchitektur möglicherweise noch um. Die Hardware könnte die falschen Daten erhalten (angenommen, das Gadget ist auf die Hardware-E/A abgebildet). Die Speichersperre wird zwischen Daten und Befehlszuweisung benötigt.
In der von Dennis Ritchie entworfenen Sprache verhielt sich jeder Zugriff auf ein beliebiges Objekt, mit Ausnahme von automatischen Objekten, deren Adresse noch nicht bekannt war, so, als würde die Adresse des Objekts berechnet und dann der Speicher an dieser Adresse gelesen oder beschrieben. Dies machte die Sprache sehr leistungsfähig, schränkte aber die Optimierungsmöglichkeiten stark ein.
Es wäre zwar möglich gewesen, einen Qualifier hinzuzufügen, der den Compiler auffordert, davon auszugehen, dass ein bestimmtes Objekt nicht auf seltsame Weise verändert wird, aber eine solche Annahme wäre für die große Mehrheit der Objekte in C-Programmen angemessen, und es wäre unpraktisch gewesen, einen Qualifier für alle Objekte hinzuzufügen, für die eine solche Annahme angemessen wäre. Andererseits müssen einige Programme einige Objekte verwenden, für die eine solche Annahme nicht gelten würde. Um dieses Problem zu lösen, sagt der Standard, dass Compiler davon ausgehen können, dass Objekte, die nicht deklariert sind volatile
werden nicht in einer Weise beobachtet oder verändert, die außerhalb der Kontrolle des Compilers liegt oder die ein vernünftiger Compiler nicht verstehen würde.
Da es auf verschiedenen Plattformen unterschiedliche Möglichkeiten gibt, Objekte außerhalb der Kontrolle eines Compilers zu beobachten oder zu verändern, sollten sich die Qualitätscompiler für diese Plattformen in ihrer genauen Handhabung von volatile
Semantik. Da die Norm leider nicht vorschlägt, dass Qualitätscompiler, die für die Low-Level-Programmierung auf einer Plattform bestimmt sind, mit volatile
in einer Art und Weise, die alle relevanten Auswirkungen einer bestimmten Lese-/Schreiboperation auf dieser Plattform erkennt, sind viele Compiler nicht in der Lage, dies auf eine Art und Weise zu tun, die es schwieriger macht, Dinge wie Hintergrund-E/A auf eine Art und Weise zu verarbeiten, die effizient ist, aber nicht durch Compiler-"Optimierungen" unterbrochen werden kann.
Flüchtig bedeutet, dass sich die Speicherung jederzeit ändern kann, was aber außerhalb der Kontrolle des Benutzerprogramms liegt. Das bedeutet, dass das Programm bei einem Verweis auf die Variable immer die physikalische Adresse (d.h. ein zugeordnetes Eingabefifo) prüfen und nicht im Cache verwenden sollte.