Was bedeutet—oder hat—"volatile void function( ... )" zu tun?
Ich habe gesehen, Wie viele Nutzung ist "volatil" - Schlüsselwort in C++ - Funktion, die aus der Grammatik Perspektive? über die Verwendung des volatile-Schlüsselwort auf Funktionen, aber es gab keine klare Erklärung, was Fall 1 aus, dass die Frage kam. Nur eine Aussage von einem der Befragten, dass es schien sinnlos/nutzlos.
Doch ich kann nicht ganz akzeptieren, dass die Aussage, da der AES-software-Implementierung für GNUC verwendet wurden für buchstäblich Jahre, und Sie haben eine Reihe von Funktionen, wie:
INLINE volatile void functionname( /* ... */ ) {
/* ... */
asm( /* ... */ ) //embedded assembly statements
/* ... */
}
Es muss einen Grund gegeben haben, für, die Nutzung. Kann mir jemand:
Eine. sagen Sie mir, was der ursprüngliche Grund war; und
B. wie zur Erzielung der gewünschten Wirkung nun?
Ich bin mit Ubuntu und GCC 4.6.3.
Hinweis: Der nächste, den ich bin gekommen, um eine Erklärung dafür ist, dass vor GCC 2.5, könnten Sie fälschen die 'noreturn' - Attribut umgesetzt wurde in 2.5 über die folgenden:
void fatal( /* ... */ ) { /* ... */ exit(1); }
typedef void voidfn ();
volatile voidfn fatal;
Dies würde erlauben, dass der compiler erkennt, dass "tödlich" war nicht zurückkehren.
Aber das Szenario scheint nicht zu gelten für die AES-code. Es ist schon eine lange Zeit, da habe ich alles in Assembler, aber ich glaube, ich würde erkennen, ein Sprung oder sowas.
InformationsquelleAutor der Frage EdwinW | 2013-01-12
Du musst angemeldet sein, um einen Kommentar abzugeben.
Entsprechend der gcc-Dokumentation (bis Februar 2015)
volatile void
als Rückgabewert einer Funktion in C (aber nicht in C++) ist äquivalent zu__attribute__((noreturn))
auf die Funktion und informiert den compiler, dass die Funktion nie zurückkehrt.InformationsquelleAutor der Antwort Chris Dodd
Den C99-standard sagt, dass dies in §6.7.3/3:
§6.2.5/19 sagt:
§6.3.2.1/1 sagt:
Daher
void
ist kein lvalue, also die type qualifiers (const
volatile
undrestrict
) sind nicht sinnvoll ist, für Ausdrücke der Formvoid
. Also, in jedem C99-kompatible compilerconst void
undvolatile void
sinnlos sind (obwohl Zeiger zuconst void
undconst volatile
sind sinnvoll).Weiterhin die Einschränkungen des §6.9.1/3 disallow eine Funktion zur Rückgabe eines qualifizierten Art der
void
:Da dies eine Einschränkung darstellt, ein konformer compiler muss Problem eine diagnostische (§5.1.1.3/1). So eine Funktion zurückgeben
volatile void
ist nicht erlaubt in C99.Als für das, was
volatile void
verwendet haben, zu tun, ich habe keine Ahnung und kann nicht wirklich spekulieren. Der AES-code, den Sie suchen, wahrscheinlich nur alte Reste, die nie aufgeräumt, Schätze ich.InformationsquelleAutor der Antwort Adam Rosenfield
REFERENZEN
https://github.com/nmoinvaz/minizip/blob/master/aes/aes_via_ace.h Siehe Linien 323 durch 333 und Linien 399 über 492. Es gibt viele andere Plätze zu finden, die diesem code, das war nur die erste, die ich stolperte über.
http://www.open-std.org/jtc1/sc22/wg14/docs/rr/dr_113.html Danke @ouah!
http://opencores.org/ocsvn/openrisc/openrisc/trunk/gnu-old/binutils-2.18.50/gas/testsuite/gas/i386/padlock.d Stellte sich bis auf eine Suche nach "f3 0f a7", und identifiziert die opcodes als spezialisierte Verschlüsselungs-Operationen.
GCC "info" - Dokumentation.
BEWEISE
volatile void function(...)
ist nicht streng konform zu C99. (Danke @Adam und @ouah. @Adam, die für das Graben in der C99-spec, und @ouah für den Hinweis mich bei der DR die oben aufgeführt sind.)GCC Hinzugefügt
__attribute__((noreturn))
in der version 2.5 als Ersatz fürvolatile void
sondern hat weiterhin zu akzeptierenvolatile void
so spät wie version 4.6.3 unterstützen die code-Kompatibilität mit dem Compiler vor version 2.5. (GCC-Dokumentation).Den code oben verwiesen hat in der Tat die Steuerung zurück zu, wo es hieß aus, wie in der Anleitung erscheinen nicht zu manipulieren, die Adresse registrieren(s), noch führen Sie ein jump-Befehl. Stattdessen laden verschiedene Werte in der 32-bit-Register. (Code-Prüfung.)
Die Befehle in den Zeilen 323 durch 333 spezielle opcodes in die Unterstützung von Verschlüsselungs-Operationen. (Code-Prüfung sowie die "Vorhängeschloss" - code.)
Den code mit der Montage funktioniert offensichtlich von Ihnen erwartet, um zurückzukehren. (Code-Prüfung.)
Den
noreturn
- Attribut sagt dem compiler, dass die Funktion nicht zurück, so kann der compiler Optimierungen machen. (GCC-Dokumentation).Aus der GCC-Dokumentation: nicht davon ausgehen, dass Registern gespeichert, die von der aufrufenden Funktion wiederhergestellt sind, bevor Sie die noreturn-Funktion.
LÖSUNG
Es wurde eine Diskussion mit einem Kollegen, endlich hat mich eines besseren belehrt. Der compiler muss etwas anders machen, wenn eine Funktion deklariert, dass er nicht zurückkehren. Prüfung der GCC-Dokumentation dazu bestätigt.
A. Der ursprüngliche Grund
Müssen Sie sich Fragen, die folgende Frage zu stellen.
Frage: Der AES-code speziell lädt die Werte in die 32-bit-Register, und führt Operationen auf Sie. Wie kann man die Antworten zu den restlichen code?
Antwort: Den GCC-Optimierungen bedeuten, dass die aufrufende Funktion die Register, die sonst überschrieben, die Werte zurückgeben, werden nicht gespeichert. Die Ergebnisse der Berechnungen im Assembler-Funktionen bleiben in den Registern, die für den nachfolgenden code verwenden.
B. Erreichung der gewünschten Wirkung nun:
Ziemlich viel lassen Sie es allein. Die einzige Sache, die Sie tun, ist ersetzen Sie den
volatile void
Gegenzug geben Sie einfachvoid
und fügen Sie dienoreturn
Attribut an den Funktionen. Theoretisch sollte das genau die gleiche Wirkung. In der Praxis, it ain 'T broke, don' T fix it.ZWECKMÄßIGKEIT
Umfangreichen Einsatz dieser Technik ist definitiv abgeraten. Zunächst kommt es auf die Anpassung für den jeweiligen compiler. Zweitens, es hängt davon ab, auf denen Compiler, die sich nicht ändern, wie Sie behandeln die 'no return' Fall. Drittens ist es möglicherweise verwirrend, um spätere Betreuer.
Die einzige situation, wo so etwas sinnvoll ist, wenn Sie unter Ausnutzung von hoch spezialisierten Maschinen-code, zu erreichen, die sonst unmöglich Verbesserung in der Geschwindigkeit. Selbst dann sollte es ausgewogen sein, gegen die Kompromisse.
In diesem Beispiel genau zwei Compilern unterstützt werden, und nur wenn die Maschinen über die spezielle hardware-Unterstützung zu nutzen. Ansonsten, es ist alles bearbeitet durch die standard-C-code. Das ist eine Menge Aufwand. Stellen Sie sicher, dass es sich auszahlen, bevor Sie es tun.
InformationsquelleAutor der Antwort EdwinW