volatile und Zuweisungen

16/08/2015 - 16:42 von Thomas Richter | Report spam
Hallo miteinander,

neulich bin ich über folgenden Code gestolpert:

struct Custom {}; /* <-- irgendwelche Hardwareregister */

volatile struct Custom *custom = (volatile struct Custom *)...
/*irgendwelche Hardware addresse */

Jetzt greift der Code auf die Hardwareregister wie folgt zu:

custom->rega = custom->regb = 0x00;

Das interessante hierbei ist, dass die Hardwareregister nur
Schreibregister sind, und wenn man versucht, aus diesen Registern zu
lesen haben sie eine andere Funktion. Ist so unüblich nicht.

Ich hatte bislang den Eindruck, das Resultat des Zuweisungsoperators ist
die rechte Seite, also 0x00, womit obiges àquivalent zu

custom->rega = 0x00;
custom->regb = 0x00;

wàre, jedoch ohne eine Reihenfolge der Zuweisung zu definieren (kein
Sequenzpunkt).

Interessanterweise übersetzt der hier gebrauchte Compiler das ganze zu:

custom->regb = 0;
custom->rega = custom->regb;

und führt somit einen Lesevorgang aus, der natürlich Unfug erzeugt.
Interessanterweise *trotz* des "volatile"-Qualifiers.

Ich bin mir nicht ganz im Klaren, ob ein derartiger Compiler konform zum
C-Standard verhàlt. "volatile" sollte den Compiler eigentlich darauf
hinweisen, dass man auf die Elemente der Struktur nicht
nebenwirkungsfrei zugreifen kann, und das Ergebnis der Zuweisung ist ja
der rechte Operand, und nicht der Inhalt des linken. Trotzdem ensteht
"defekter Code".

Andererseits kann man sagen, dass der Effekt von "volatile"
implementierungsabhàngig ist und vom Standard nicht genau definiert ist.
Das Compilermanual (ja, gibt es in der Tat, zwei dicke Binder) schweigt
sich leider zum Thema "volatile" aus.

Meinungen und Kommentare hierzu?
 

Lesen sie die antworten

#1 Bernd Nawothnig
16/08/2015 - 17:46 | Warnen spam
On 2015-08-16, Thomas Richter wrote:
neulich bin ich über folgenden Code gestolpert:

struct Custom {}; /* <-- irgendwelche Hardwareregister */

volatile struct Custom *custom = (volatile struct Custom *)...
/*irgendwelche Hardware addresse */

Jetzt greift der Code auf die Hardwareregister wie folgt zu:

custom->rega = custom->regb = 0x00;

Das interessante hierbei ist, dass die Hardwareregister nur
Schreibregister sind, und wenn man versucht, aus diesen Registern zu
lesen haben sie eine andere Funktion. Ist so unüblich nicht.

Ich hatte bislang den Eindruck, das Resultat des Zuweisungsoperators ist
die rechte Seite, also 0x00, womit obiges àquivalent zu

custom->rega = 0x00;
custom->regb = 0x00;

wàre, jedoch ohne eine Reihenfolge der Zuweisung zu definieren (kein
Sequenzpunkt).

Interessanterweise übersetzt der hier gebrauchte Compiler das ganze zu:

custom->regb = 0;
custom->rega = custom->regb;

und führt somit einen Lesevorgang aus, der natürlich Unfug erzeugt.
Interessanterweise *trotz* des "volatile"-Qualifiers.



Der besagt ja auch nur, dass sich der Wert der Variablen àndern kann,
also etwa nicht in Registern zwischengespeichert werden darf. Ich
wette, diese Variante entsteht sogar nur, *weil* du volatile verwendet
hast, denn nun darf der Compiler gar nicht mehr die Konstante 0
verwenden, denn so hast Du es oben nicht hingeschrieben.

Von weiteren Nebenwirkungen weiß der Compiler nichts und muss das auch
gemàß Sprachspezifikation nicht wissen.

Ich bin mir nicht ganz im Klaren, ob ein derartiger Compiler konform zum
C-Standard verhàlt. "volatile" sollte den Compiler eigentlich darauf
hinweisen, dass man auf die Elemente der Struktur nicht
nebenwirkungsfrei zugreifen kann,



Nein. Es heißt nur, dass der Wert der Variablen sich asynchron, also
von außen angestoßen, àndern kann. Von verbotenen Leseoperationen ist
dort keineswegs die Rede.

und das Ergebnis der Zuweisung ist ja der rechte Operand, und nicht
der Inhalt des linken. Trotzdem ensteht "defekter Code".

Andererseits kann man sagen, dass der Effekt von "volatile"
implementierungsabhàngig ist und vom Standard nicht genau definiert ist.
Das Compilermanual (ja, gibt es in der Tat, zwei dicke Binder) schweigt
sich leider zum Thema "volatile" aus.

Meinungen und Kommentare hierzu?



Guckst Du etwa hier:

http://www2.informatik.uni-halle.de...volat.html

Das Schlüsselwort volatile teilt dem Compiler mit, daß die mit name
bezeichnete Variable mit dem Datentyp typ durch Ereignisse außerhalb
der Kontrolle des Programms veràndert werden kann.

Der Wert der Variablen muß deshalb vor jedem Zugriff neu aus dem
Hauptspeicher eingelesen werden, d.h. er darf nicht in einem Register
des Prozessors zwischengespeichert werden.

Der Compiler arbeitet bei mit volatile deklarierten Variablen ohne
jede Optimierung, d.h. làßt die entsprechenden Werte bei jedem Zugriff
neu aus dem Hauptspeicher laden und sorgt bei Verànderungen dafür, daß
die neuen Werte ohne Verzögerung dort sofort abgelegt werden.

Beispiel:

#include <time.h>

volatile time_t zeit;

volatile verhindert bestimmte Optimierungsmaßnahmen des Compilers,
es sorgt dafür, daß Operationen so ausgeführt werden, wie sie im
Quelltext notiert werden, d.h. zum Beispiel, es werden keine
Umstellungen vorgenommen und Werte werden nicht in einem Cache
gehalten, d.h. verànderte Werte werden nicht "zurückgehalten".





Bernd

no time toulouse

Ähnliche fragen