gcc, strict-aliasing und Horrorgeschichten
In gcc-strict-aliasing-und-casting-über-eine-union ich fragte, ob noch jemand Probleme mit union Zweideutigkeiten über Zeiger. Bisher scheint die Antwort zu sein Keine.
Diese Frage ist breiter: Sie haben alle horror-Geschichten über gcc und strict-aliasing?
Hintergrund: Zitat aus AndreyT Antwort im c99-strict-aliasing-Regeln-in-c-gcc:
"Strict-aliasing-Regeln sind verwurzelt in Teile des Standards in C und C++ seit Anfang [standardisierten] mal. Die Klausel verbietet den Zugriff auf Objekt des Typs durch ein lvalue eines anderen Typs ist in C89/90 (6.3) als auch in C++98 (3.10/15). ... Es ist nur so, dass nicht alle Compiler wollte (oder gewagt), um ihn durchzusetzen oder sich darauf verlassen."
Gut, gcc ist jetzt gewagt, so zu tun, mit seiner -fstrict-aliasing
wechseln. Und dies verursacht einige Probleme. Siehe z.B. den exzellenten Artikel http://davmac.wordpress.com/2009/10/ über ein Mysql-bug, und das ebenso ausgezeichnete Diskussion in http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html.
Einige andere weniger relevante links:
- Leistung-Wirkung-von-fno-strict-aliasing
- strict-aliasing
- wenn-ist-char-sicher-für-strenge-Zeiger-aliasing
- wie-zu-erkennen-strict-aliasing-at-compile-time
So zu wiederholen, haben Sie eine horror-Geschichte, die Ihrer eigenen? Probleme nicht gekennzeichnet durch -Wstrict-aliasing
würde, natürlich, werden bevorzugt. Und andere C-Compiler sind auch willkommen.
Hinzugefügt 2. Juni: Der erste link in Michael Burr ' s Antwort, die nicht ja qualifizieren, als eine horror-Geschichte ist, ist vielleicht ein bisschen veraltet (von 2003). Ich habe einen schnellen test, aber das problem ist anscheinend Weg.
Quelle:
#include <string.h>
struct iw_event { /* dummy! */
int len;
};
char *iwe_stream_add_event(
char *stream, /* Stream of events */
char *ends, /* End of stream */
struct iw_event *iwe, /* Payload */
int event_len) /* Real size of payload */
{
/* Check if it's possible */
if ((stream + event_len) < ends) {
iwe->len = event_len;
memcpy(stream, (char *) iwe, event_len);
stream += event_len;
}
return stream;
}
Den spezifischen Beschwerde ist:
Einige Benutzer haben sich beschwert, dass, wenn der [oben] - code kompiliert wird, ohne die -fno-strict-aliasing, die Reihenfolge der schreiben und memcpy ist invertiert (das heißt, eine Schein-len mem-kopiert in den Bach).
Kompilierten code, mit gcc 4.3.4 auf CYGWIN-wih -O3 (bitte korrigiert mich wenn ich falsch bin-mein assembler ist etwas eingerostet!):
_iwe_stream_add_event:
pushl %ebp
movl %esp, %ebp
pushl %ebx
subl $20, %esp
movl 8(%ebp), %eax # stream --> %eax
movl 20(%ebp), %edx # event_len --> %edx
leal (%eax,%edx), %ebx # sum --> %ebx
cmpl 12(%ebp), %ebx # compare sum with ends
jae L2
movl 16(%ebp), %ecx # iwe --> %ecx
movl %edx, (%ecx) # event_len --> iwe->len (!!)
movl %edx, 8(%esp) # event_len --> stack
movl %ecx, 4(%esp) # iwe --> stack
movl %eax, (%esp) # stream --> stack
call _memcpy
movl %ebx, %eax # sum --> retval
L2:
addl $20, %esp
popl %ebx
leave
ret
Und für den zweiten link in Michaels Antwort,
*(unsigned short *)&a = 4;
gcc wird meist (immer?) geben Sie eine Warnung. Aber ich glauben eine gültige Lösung zu diesem (für gcc) ist zu verwenden:
#define CAST(type, x) (((union {typeof(x) src; type dst;}*)&(x))->dst)
//...
CAST(unsigned short, a) = 4;
Ich habe gefragt, ob das OK ist in gcc-strict-aliasing-und-casting-über-eine-unionaber bisher niemand widerspricht.
InformationsquelleAutor der Frage Joseph Quinsey | 2010-06-02
Du musst angemeldet sein, um einen Kommentar abzugeben.
Keine horror-Geschichte meiner eigenen, aber hier sind einige Zitate von Linus Torvalds (sorry wenn diese schon in einem der verlinkten Referenzen in der Frage):
http://lkml.org/lkml/2003/2/26/158:
(Anmerkung im Nachhinein: dieser code ist in Ordnung, aber die Linux-Implementierung von
memcpy
wurde ein makro, das cast, dielong *
kopieren in größeren Blöcken. Mit korrekt definiertenmemcpy
gcc -fstrict-aliasing
ist nicht erlaubt, diese zu brechen-code. Aber es bedeutet, dass Sie inline-asm zu definieren, einen kernelmemcpy
wenn dein compiler nicht wissen, wie drehen eine byte-Kopie-Schleife in effiziente asm, das war der Fall für den gcc vor gcc7)http://www.mail-archive.com/[email protected]/msg01647.html:
InformationsquelleAutor der Antwort Michael Burr
SWIG generiert code, hängt von strengen aliasing deaktiviert, die kann dazu führen,alle Arten von Problemen.
InformationsquelleAutor der Antwort paleozogt
gcc, aliasing-und 2-D-variable-length-arrays: Der folgende code kopiert eine 2x2-matrix:
Mit gcc 4.1.2 auf CentOS, bekomme ich:
Ich weiß nicht, ob das allgemein bekannt, und ich weiß nicht, ob das ein bug oder ein feature ist. Kann ich nicht duplizieren das problem mit gcc 4.3.4 auf Cygwinso kann es haben, wurde behoben. Einige Workarounds:
__attribute__((noinline))
zum kopieren().-fno-strict-aliasing
.b[][n]
zub[][2]
.-O2
oder-O3
.Weitere Hinweise:
copy()
wie diese. (Und, nebenbei, ich war etwas überrascht zu sehen, dass gcc nicht entrollen die Doppel-Looping.)-Wstrict-aliasing=
hat hier nichts.Update: Das oben nicht wirklich beantworten die OP ' s Frage, da er (also ich) wurde gefragt, über die Fälle, wo strenge aliasing 'legitim' brach Ihr code, in der Erwägung, dass die oben genannten einfach zu sein scheint, eine Garten-Sorte compiler-Fehler.
Ich meldete es GCC Bugzillaaber Sie waren nicht daran interessiert, die alte 4.1.2, obwohl (ich glaube) es ist der Schlüssel zu der $1-Milliarden-RHEL5. Kommt es nicht in 4.2.4.
Und ich habe einen etwas einfacheren Beispiel von einem ähnlichen bug, mit nur einer matrix. Der code:
produziert die Ergebnisse:
Es scheint, ist es die Kombination
-fstrict-aliasing
mit-finline
die Ursachen der Fehler.InformationsquelleAutor der Antwort Joseph Quinsey
Der folgende code gibt 10 unter gcc 4.4.4. Ist etwas falsch mit der union-Methode oder gcc-4.4.4?
InformationsquelleAutor der Antwort user470617
hier ist meiner:
http://forum.openscad.org/CGAL-3-6-1-causing-errors-but-CGAL-3-6-0-OK-tt2050.html
es verursacht bestimmte Formen in einem CAD-Programm gezeichnet werden, falsch. danken Sie Güte, die für das Projekt Staats-und Regierungschefs den Aufbau einer regression test-suite.
den Fehler nur manifestierte sich, auf bestimmten Plattformen, die mit älteren Versionen von GCC und ältere Versionen bestimmter Bibliotheken. und dann nur mit -O2 aktiviert. -fno-strict-aliasing gelöst.
InformationsquelleAutor der Antwort don bright
Den Gemeinsamen anfangs-Sequenz-Regel C verwendet werden interpretiert, wie es
möglich, eine Funktion schreiben, die arbeiten könnten auf der führende Teil eines
Vielzahl von Struktur-Typen, vorausgesetzt, Sie beginnen mit Elementen der passenden
Typen. Unter C99, die Regel wurde so geändert, dass es nur angewendet, wenn die Struktur
Arten beteiligt waren Mitglieder der gleichen Gewerkschaft, deren komplette Erklärung war sichtbar am point-of-use.
Die Autoren von gcc darauf bestehen, dass die betreffende Sprache ist nur anwendbar, wenn
die Zugriffe erfolgen über die union-Typ, ungeachtet der Tatsachen
:
Gäbe es keinen Grund, um anzugeben, dass die komplette Erklärung muss sichtbar sein, wenn die Zugriffe ausgeführt werden musste, über die union geben.
Obwohl die CIS-Regel beschrieben wurde in Bezug auf die Gewerkschaften, Ihre primären
nutzen lag in dem, was Sie stillschweigend über die Art und Weise in die Strukturen wurden
angelegt und darauf zugegriffen. Wenn S1 und S2 waren Strukturen, die gemeinsam eine CIS,
gäbe es keine Möglichkeit, dass eine Funktion, die das akzeptiert einen Zeiger auf ein S1
und ein S2 von einer externen Quelle zur Einhaltung C89 der CIS-Regeln
ohne dass sich das gleiche Verhalten, um nützlich zu sein mit Zeigern auf
Strukturen, die nicht eigentlich in einer union-Objekt; die Angabe CIS
Unterstützung für Strukturen hätte damit redundante gegeben, dass es war
bereits für die Gewerkschaften.
InformationsquelleAutor der Antwort supercat