Strict pointer aliasing: Gibt es eine Lösung für ein bestimmtes Problem?

8

Ich habe ein Problem, das durch das Brechen der strikten Aliasing-Regel des Zeigers verursacht wird. Ich habe den Typ T , der von einer Vorlage kommt, und einen ganzzahligen Typ Int der gleichen Größe (wie bei sizeof ). Mein Code macht im Wesentlichen folgendes:

%Vor%

Da T ein beliebiger Wert ist (außer der Größenbeschränkung), der einen Konstruktor haben könnte, kann ich keine Union von T und Int erstellen. (Dies ist nur in C ++ 0x erlaubt und wird noch nicht einmal von GCC unterstützt).

Gibt es irgendeine Möglichkeit, den obigen Pseudocode neu zu schreiben, um die Funktionalität zu erhalten und die strengen Aliasing-Regeln zu umgehen? Beachten Sie, dass dies eine Vorlage ist, ich kann T oder den Wert von some_other_t nicht kontrollieren; Die Zuordnung und der anschließende Vergleich finden innerhalb des Vorlagencodes statt.

(Zur Erinnerung, der obige Code begann mit GCC 4.5 zu brechen, wenn T irgendwelche Bitfelder enthält.)

    
doublep 05.06.2010, 15:23
quelle

6 Antworten

1
%Vor%

Auf meinem System optimiert GCC sowohl is_T_0() als auch memcpy() , was zu einigen wenigen Assemblierungsanweisungen in myfunc() führt.

    
Daniel Stutzbach 05.06.2010, 21:44
quelle
1

Haben Sie von boost::optional gehört?

Ich muss zugeben, dass mir das wahre Problem hier unklar ist ... aber boost :: optional erlaubt es, nach Wert zu speichern und trotzdem zu wissen, ob der eigentliche Speicher initialisiert wurde oder nicht. Ich lasse auch Konstruktion und Zerstörung an Ort und Stelle zu, also könnte eine gute Passform sein, denke ich.

BEARBEITEN :

Ich glaube, ich habe das Problem endlich verstanden: Sie möchten viele Objekte an verschiedenen Stellen im Speicher zuweisen können, und Sie möchten wissen, ob der Speicher zu diesem Zeitpunkt wirklich ein Objekt enthält oder nicht .

Leider hat Ihre Lösung ein großes Problem: Sie ist falsch. Wenn T irgendwie durch ein null Bitmuster dargestellt werden kann, dann wird es sich um einen unitären Speicher handeln.

Sie müssen sich dazu entscheiden, mindestens ein Bit Information hinzuzufügen. Es ist nicht wirklich viel, immerhin sind das nur 3% Wachstum (33 Bits für 4 Bytes).

Sie könnten zum Beispiel einige mimick boost::optional verwenden, aber in einer Array-Art (um den Padding-Verlust zu vermeiden).

%Vor%

Dann ist es so einfach:

%Vor%

Hinweis : Der Einfachheit halber habe ich das Problem der Ausrichtung nicht berücksichtigt. Wenn du nichts über das Thema weißt, lies darüber, bevor du an der Erinnerung herumfummelst:)

    
Matthieu M. 05.06.2010 16:30
quelle
1

Wie wäre es damit:

%Vor%

Es ist möglicherweise nicht so effizient, aber es sollte die Warnung loswerden.

ANHANG # 1:

Da T auf die gleiche Größe wie Int beschränkt ist, stellen Sie sich einen Dummy-bitweisen Null-Wert vom Typ T vor und vergleichen Sie direkt mit ihm (anstelle des Vergleichs und des Vergleichs von agaist Int(0) ).

Wenn Ihr Programm single-threaded ist, könnten Sie etwas wie folgt haben:

%Vor%

Wenn es sich um ein Multithreading handelt, sollten Sie vermeiden, ein statisches Mitglied zero_ zu verwenden und jede Containerinstanz ihr eigenes zero_ -Member zu besitzen:

%Vor%

ANHANG # 2:

Lassen Sie mich den obigen Zusatz auf eine andere, einfachere Weise stellen:

%Vor%     
Emile Cormier 05.06.2010 15:48
quelle
1

Warum nicht einfach:

%Vor%

(Vielleicht möchten Sie auch versuchen, das static -Qualifikationsmerkmal zu zero hinzuzufügen, um zu sehen, ob es leistungsabhängig ist)

    
CAFxX 15.07.2012 07:14
quelle
0

Verwenden Sie einen 33-Bit-Computer. ;-P

    
Emile Cormier 05.06.2010 18:12
quelle
-2

Es fühlt sich an wie ein Hack, aber anscheinend habe ich eine Lösung gefunden: mit volatile für Int casting. Im Wesentlichen mache ich jetzt Folgendes:

%Vor%

Das Problem mit bitfield T ist jetzt weg. Trotzdem bin ich nicht ganz glücklich darüber, da volatile in C ++ AFAIK nicht gut definiert ist ...

    
doublep 05.06.2010 18:19
quelle