volatile ?!
-
Danke aber warum funktioniert der Codeauschitt unter linux und nicht unter win32 ?!
/*Global Variablen*/
unsigned short zeit;
unsigned long lastic;
volatile unsigned long tic10;
/******************//*Codeauschnitt*/
zeit = (unsigned short) (tic10-lastic);
if (zeit != 0)
{
/***************/in der zeile:
zeit = (unsigned short) (tic10-lastic);
bleibt das programm stehen wo es unter Linux funktioniert.
aendere ich das auf
zeit = (unsigned short) (1-lastic);geht es zwar - ist aber nicht sinn und zweck.
mfg Oliver Kern
-
Dann mach halt tic10 non-volatile
-
geht auch nicht.
mfg Oliver Kern
-
Dann liegt der Fehler woanders.
Wo wird tic10 denn verändert?
-
volatile würd ich am ehesten mit "Compiler untersteh dich da irgendwas dran zu optimieren sonst gibts Tote" bezeichnen.
Klappt zwar nicht immer, aber du hast ihn gewarnt und 'meistens' funktioniert es auch.und tic10 wird ein dem obigen Codeausschnitt nicht verändert, ob das beim Rest der Fall ist muss aber wer sagen dessen Kristallkugel grad nicht zur Reperatur ist.
-
Sehe da nichts Konsolenspezifisches...
Verschoben nach C++.
MfG SideWinder
-
Also ich kenne volatile nur im Zusammenhang mit dem Zeitgeber (Ticks).
volatile unsigned int far *iTimer = (volatile unsigned int far *) 0x46c;
Die Ticks werden Mitternacht auf 0 gesetzt, soviel ich weiß, und hochgezählt. 18,2 Ticks entsprechen ungefähr einer Sekunde.
Das Problem liegt wahrscheinlich daran, dass neuere Compiler (damit meine ich z. B. den VC++) dies nicht mehr unterstützen. Genauso wie all die anderen tollen Sachen, die man noch in DOS machen konnte.Probiers mit einem 16Bit-Compiler aus und es wird funktionieren. Also bei mir funktionierts mit dem Borland 3.x (dürfte aber auch noch mit Borland 5.02 funktionieren).
Ich vermute, dass cd9000 es am besten getrofen hat mit:
AFAIK ist die Aussage: "Lieber Compiler, steck diese Variable nicht in irgendwelche Register, denn du weißt nicht, wann sie sich spontan verändert."
PS: VIELEN DANK @SideWinder, dass du genau dann das Thema verschieben musst, wenn ich ne Antwort schreibe!!!
-
das wird gebraucht, wenn mehrere threads ueber shared memory kommunizieren sollen.
dann darf der compiler z.b. keinen lesezugriff rausoptimieren, auch wenn seiner meinung nach inzwischen keine veraenderung stattgefunden hat.
fuer das mit den methoden faellt mir auch grad kein beispiel ein.
-
eine volatile Funktion besagt doch nur, dass man sie auch für ein Objekt, von der klasse mit der volatilen funktion, aufrufen kann.
Sprich:int main () { extern volatile Objekt *o; o->doSomething (); }
dann muss doSomething volatile sein, sonst klappt der aufruf nicht.
und damit doSomething volatile sein darf, darf es nur auf volatile elementvariablen der klasse objekt zugreifen. und damit wiederum ist gesichert, dass das volatile Objekt volatile bleibt.zumindest hab ich das bis jetzt so verstanden
-
Hallo AJ und allen anderen,
Also ich kenne volatile nur im Zusammenhang mit dem Zeitgeber (Ticks)
da kommen wir naeher - was mein Problem angeht.
Unter Linux wird Tic10 hoch gezaehlt (Compiler):
zeit = (UWORD) (tic10-lastic); if (zeit != 0) { lastic = tic10; printf("TIC10:%d",tic10);
Gibt es eine alternative fuer VC++ ?!
mfg Oliver Kern
-
das wird gebraucht, wenn mehrere threads ueber shared memory kommunizieren sollen.
Das ist ein verbreiteter Irrglaube, dem selbst A. Alexandrescu in seinem Artikel:
volatile — Multithreaded Programmer’s Best Friendhvolatile erliegt (ansonsten ist der Artikel aber sehr gut). volatile hat *nichts* mit Threads zu tun. Standard-C++ kennt dieses Konzept nicht.
Ein paar Richtigstellungen zum oben genannten Artikel findet man hier: http://www.cuj.com/documents/s=7996/cujcexp1904alexandr/alexandr.htm#1Und viel mehr als nur das übliche zum Thema volatile liefert eine Suche in comp.lang.c++.modereated.
-
ich schreibe nicht in C++ sondern nur C.
mfg Oliver Kern.
-
Das macht nix, die Aussagen gelten genauso für C.
Für den VC kannst Du eine Windows-Funktion aufrufen GetTickCount() - #include <windows.h> - der Trick mit der Variablen entfällt dann.
Allgemein findet man volatile nicht oft auf PCs! volatile zwingt den Compiler, bei jedem Zugriff auf eine Variable diese erneut auszulesen. Bei "normalen" Variablen kann der Compiler den letzten Wert nach dem Lesen ja beliebig lange irgendwo speichern (z.B. weil er schleifeninvariant ist).
Ständig trifft man sowas auf Embedded Systemen an, wo man Variablen direkt auf I/O-Ports mappt.
Nehmen wir an, ein Digitaler 16-Bit-Bus mit Eingängen ist direkt im Adressraum ab der Adresse 0xffe0 eingeblendet. Nun will ich warten, bis der Eingang Bit 3 auf 1 geht:
dword* pIOPort; pIOPort = 0xffe0; // ein Embedded Compiler wird sowas klaglos tun... evtl. // gibt's auch ein #pragma dafür while ( ! ( (*pIOPort) & 0x03 ) ) { }
Nun, das ist eine klassische Endlosschleife! Der Compiler lädt den Wert von *pIOPort irgendwo in ein Register und vergleicht den nun 1000000000000ganzoft mit 0x03. Und bleibt hier hängen, Ende Gelände. Selbst wenn der Eingang auf 1 geht, bleibt das Programm trotzdem stehen, da der geänderte Wert nicht mehr erkannt wird.
Ein volatile
volatile dword* pIOPort;
dagegen führt dazu, daß bei jedem Vergleich der Wert *pIOPort erneut gelesen wird. Die Schleife wartet nun so lange, bis tatsächlich der Vergleich erfüllt ist und das Programm funktioniert.
Und nun sollte auch klar sein, wie tic10 funktioniert! Und warum das volatile ist.
Die entsprechende Variante unter dem VC erledigt das über eine Funktion und braucht daher dies nicht, ist also nicht direkt vergleichbar.
-
Original erstellt von HumeSikkins:
**[quote] das wird gebraucht, wenn mehrere threads ueber shared memory kommunizieren sollen.
****
Das ist ein verbreiteter Irrglaube...**[/QUOTE]
Häää? Wieso ist das ein Irrglaube? Oben hast Du selber ein Beispiel mit dem Port gegeben, wobei ein externes Ereignis (z.B. ein eingehndes Zeichen am UART-Chip) den Wert an der Speicherstelle ändert. Das ist das selbe, wie ein zweiter Thread, der den Inhalt an der Speicherstelle ändert!volatile ist das Gegenteil von register. Weist man den Compiler an, den Code auf Geschwindigkeit zu optimieren, dann wird i.d.R. jede Variable als register behandelt, ansonsten als volatile. Oft macht sich dies bei Multithreaded nicht bemerkbar. Habe selbst schon den Effekt gehabt, dass ein Programm von mir, welches sehr viele Threads verwendete auf i386 lief, aber sobald ich es für nen PowerPC übersetzt habe, kamen mit geschwindigkeits optimierter Übersetzung sporadisch merkwürdige Egebnisse dabei raus (wahrscheinlich, da der Prozessor viel mehr Register besitzt).
Natürlich muss man den Zugriff auf eine Variable immer noch vorm gleichzeitigen Zugriff anderer Threads (oder falls sie in einem shared memory liegt auch vor anderen beteiligten Prozessen) schützen (z.B. Semaphore), aber dies kann unter Umständen nicht ausreichen, da sie noch volatil deklariert werden muss.
Und was den Artikel über "ein paar Richtigstellungen" angeht (C/C++-User Journal), da bin ich der Meinung, dass der Autor mitTo make a long story short, there are systems (such as the POSIX-compliant ones) on which the volatile modifier is not needed, and there are other systems on which adding volatile will not help, leaving the program incorrect.
eher etwas Falsch darstellt, zumindestens ist es eine Halbwahrheit. Klar, lasse ich meine Variable vom OS verwalten, fängt das OS auch den Zugriff auf Speicherstellen ab, die von mehreren Prozessen verwendet wird und kann darauf entsprechend reagieren. Aber habe ich RICHTIGE Threads, kontrolliert das OS den Zugriff auf gemeinsame Speicherstellen der unterschliedlichen Thread-ID's NICHT! (z.B. kennt Linux bis heute noch keine echten Threads, sondern erzeugt eine neue Prozess-ID ohne den Speicher zu dublizieren, clone (man clone) sieht zwar soetwas vor, aber das funktioniert nicht...)
-
Natürlich muss man den Zugriff auf eine Variable immer noch vorm gleichzeitigen Zugriff anderer Threads (oder falls sie in einem shared memory liegt auch vor anderen beteiligten Prozessen) schützen
Wieso schützen? Du meinst sicher synchronisieren.
-
@wischmop2
Lies am Besten ein paar Artikel aus comp.lang.c++.moderated zum Thema volatile. Achte besonders auf Alexander Terekhov und James Kanze. Du wirst dann sicher sehen, woher mein Satz mit dem Irrglaube stammt.Ansonsten bin ich für eine Diskussion zu diesem Thema der falsche Gesprächspartner, da mir hier einfach zuviel Wissen fehlt.
[ Dieser Beitrag wurde am 02.07.2003 um 12:59 Uhr von HumeSikkins editiert. ]
-
Original erstellt von RenéG:
Wieso schützen? Du meinst sicher synchronisieren.Ja ja, hast ja recht, das meinte ich auch
Original erstellt von HumeSikkins:
Lies am Besten ein paar Artikel aus comp.lang.c++.moderated zum Thema volatile. Achte besonders auf Alexander Terekhov und James Kanze. Du wirst dann sicher sehen, woher mein Satz mit dem Irrglaube stammt.Werde ich machen, vielleicht hab ich ja etwas nicht verstanden. Schliesslich lernt man nie aus!
-
Hallo Marc++us,
nach dem Programmstart zaehlt TIC10 von 0 bis ... - unter Linux.
GetTickCount() macht aber was anderes.Was waere wenn ich TIC10 immer um ein hoch nehme - tic10++ ?
Ist das das selbe wie der Compiler macht ?mfg Oliver Kern.
-
[ Dieser Beitrag wurde am 05.07.2003 um 22:36 Uhr von MaSTaH editiert. ]