Forum: Compiler & IDEs dereferencing type-punned pointer - was ist das?


von Andy (Gast)


Lesenswert?

Ich benutze in meinem Code die folgende Funktion, die dazu gedacht ist, 
die gcc Software-Libraries zu ersetzen.

Beim Compilieren krieg ich den Fehler "warning: dereferencing 
type-punned pointer will break strict-aliasing rules". Ich konnte leider 
nichts finden, warum der Fehler auftritt und was das impliziert.

Ich würde auch lieber die Daten gleich per reference übergeben, aber 
leider ist der Prototyp nicht verhandelbar :-)
Das gezeigerte Schreiben in fpu_regs[] hat sich als am schnellsten 
herausgestellt, somit würde ich das auch ganz gerne beibehalten.

1
double __adddf3 (double,double);
2
3
double __adddf3 (double a, double b)
4
{
5
    alt_u32 * fpu_regs = (alt_u32 *) (DPFPU_BASE+0x80000000);
6
    
7
    register alt_u32 * temp_a = (alt_u32 *) &a;
8
    register alt_u32 * temp_b = (alt_u32 *) &b;
9
10
    fpu_regs[2] = temp_a[1];
11
    fpu_regs[1] = temp_a[0];
12
    fpu_regs[4] = temp_b[1];
13
    fpu_regs[3] = temp_b[0];
14
    .
15
    .
16
    .
17
18
19
    return (result);

Kann mir jemand sagen was hier passiert und wie ich die Meldung 
verhindern kann?

(den Flag -fno-strict-aliasing kenne ich, will ihn aber nach Möglichkeit 
vermeiden)

Danke,
Andy

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Mal in Blaue gegurgelt (ca. 18000 Treffer):

http://mail.opensolaris.org/pipermail/tools-gcc/2005-August/000047.html

http://www.google.de/search?hl=de&q=%22dereferencing+type-punned+pointer+will+break+strict-aliasing+rules%22&btnG=Google-Suche&meta=

Da kannst eine Union definieren und die Typ-Konvertierungen (type 
punning) erreichen, indem die Daten durch die Union geschleust werden, 
allerdings ohne Pointer zu verwenden. Bei Pointern geht GCC davon aus, 
daß Pointer nicht den gleichen Speicher adressieren, wenn die zu 
dereferenzierenden Typen nicht "fast" identisch sind (sich zB nur durch 
Qualifier unterscheiden).

Also:
1) -fno-strict-aliasing
2) Code umschreiben (Unions wie beschrieben)
3) GCC optimieren lassen und evtl. inkorrekten aber dafür dann evtl. 
schnelleren Code bekommen

von Andy (Gast)


Lesenswert?

Die vielen Treffer bei Google hatte ich auch, nur hab ich aus der Liste 
wohl die richtigen Infos nicht gefunden.

Also wenn ich das richtig seh, bleibt mir wohl nichts anders übrig als 
das über ne union zu lösen. Die oben geschriebene Zeigervariante is halt 
so schön einfach, aber zugegebenermassen wohl doch etwas 'dirty'.
Die Funktion des Codes ist bei -O2 und -O3 genau wie gewünscht, aber 
Lösung 1) gefällt  mir eigentlich nicht, wer weiss was dann alles für 
berechtigte Warnings in Zukunft mit unterdrückt werden.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Andy wrote:
> Die vielen Treffer bei Google hatte ich auch, nur hab ich aus der Liste
> wohl die richtigen Infos nicht gefunden.
>
> Also wenn ich das richtig seh, bleibt mir wohl nichts anders übrig als
> das über ne union zu lösen. Die oben geschriebene Zeigervariante is halt
> so schön einfach,

Nein, einfach finde ich das nicht. Schau mal an, welcher Code erzeugt 
wird, zB mit -save-temps -fverbose-asm (find ich aussagekräftiger als 
Dumps aus dem Assembler raus. Assemble wird damit geschrieben nach foo.s 
anstatt nach /tmp )

Adressen von Registern zu nehmen erfordert, daß für die Funktion ein 
Frame angelegt wird. Die Register werden gepushd, um Adresse nehmen zu 
können.

Mit einer Union kann das mit Register-Variablen geschehen (zumindest, 
wenn die Größe der Union "gerade" ist, also zB 1, 2, 4).

> aber zugegebenermassen wohl doch etwas 'dirty'.
> Die Funktion des Codes ist bei -O2 und -O3 genau wie gewünscht, aber
> Lösung 1) gefällt  mir eigentlich nicht, wer weiss was dann alles für
> berechtigte Warnings in Zukunft mit unterdrückt werden.

-fno-strict-aliasing unterdrückt keine Warnungen, sondern schaltet die 
entsprechende Optimierungen ab, d.h. solche, die unter der Annahme von 
strict-aliasing korrekt sind. Ohne die Option bleiben die Optimierungen 
eben aus, und damit auch Warungen, die damit im Zusammenhang stehen.

Ich schätze mal, diese Option führt kaum zu großartig 
besserem/schlechterem Code. Zudem kann man den Schalter gezielt auf die 
fraglichen Module anwenden.

Da es hier offenbar um Performance-Tweaks für ein Target mit FPU geht, 
bietet sich auch (Inline) Assembler an. Es müssen ja nur die Args in 
FPU-Register verteilt/abgeholt werden.

Weiß ja nicht, was Du vorhast, aber es kann durchaus lohnen sein, 
foo-gcc selbst anzupassen. Das würde den Call-Overhead sparen und das 
Register-Kopieren, zudem kann man genau sagen, welche REGs verwendet 
werden, und wie lange auf die FPU gewartet werden muss, etc.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.