2017-06-29 3 views
0

Im folgenden Code:Verletzt Pointer Casting wirklich das strikte Aliasing?

#include <stdio.h>    

int main(void) 
{ 
    int n = 74; 
    int * pn = &n; 

    short * sp; 

    //sp = (short *)&n; // <-- bad 
    sp = (short *)pn; // <-- fine 

    *sp = 4; 
    printf("%d\n", *sp); 

    return 0; 
} 

ist die strenge Aliasing Regel gebrochen werden? Soweit ich es verstehe, tut es das, da ein Zeiger auf einen kurzen Punkt auf einen int zeigt. Aber der Compiler beschwert sich nicht selbst kompiliert, wenn sie mit (vorausgesetzt, der Code ist in test.c)

gcc test.c -o test.exe -Wall -std=c99 -Wstrict-aliasing=2 -O3 

Es ist jedoch nicht beschweren, wenn die Linie markiert als schlecht unkommentiert ist, und der Computer markiert so fein ist kommentiert.

Kann jemand bitte erklären, ob dieser Fall wirklich die Regel bricht? Wenn ja, warum wird es vom Compiler nicht erkannt? Wenn nicht, warum nicht, denn nach dem Standard sollte es sein?

+2

Compiler-Warnungen fangen nicht alles ein, selbst Dinge, die offensichtlich erscheinen. – user2357112

+0

"der Compiler beschwert sich nicht" - willkommen in C, ohne ein Netz codieren. – chux

+0

Wählen Sie eine Sprache. C und C++ haben hier leicht abweichende Regeln. – Lundin

Antwort

2

Es ist nicht das Casting per se, das das strikte Aliasing verletzt, es ist der nachfolgende ungültige lvalue-Zugriff (Speicherneuinterpretation), der es verletzt.

Strict-Aliasing-Verletzungen sind wirklich Laufzeitverletzungen: Sie werden durch dynamische Art der Objekte definiert, auf die als lvalues ​​zugegriffen wird. Aus diesem Grund ist es nicht immer möglich, Alias-Verstöße zum Zeitpunkt der Kompilierung zu erkennen.

Betrachten Sie das folgende Code-Schnipsel nicht

short n = 0; 
int *pn = (int *) &n;  // 1 
short *sp = (short *) pn; // 2 
*sp = 4; 

Dieser Code nicht streng-Aliasing-Regeln verletzen, auch wenn sie die gleiche Besetzung (2) als Original-Code enthält. Obwohl der Zeiger pn als int * deklariert ist, zeigt er zur Laufzeit tatsächlich auf ein Objekt vom Typ short. So ist die Besetzung nach short * und die anschließende Zuordnung zum Pointee einwandfrei gültig. (Angenommen, der Zeigerwert überlebt diese Rundreise.)

In solchen Fällen versucht der Compiler offensichtlich, die allererste Besetzung in der Kette von Abgüssen einzufangen: die, die ein ziemlich offensichtlicher Vorläufer zu sein scheint Mögliche strenge Aliasing-Verletzung - Cast 1 in meinem Beispiel. Cast 2 hat ein ziemlich hohes Potential, um ein falsches Positiv zu erzeugen (wie in meinem Beispiel) und der Compiler warnt nicht davor.

+0

Compiler versucht, die allererste Besetzung in der Kette der Casts zu fangen, die eine potentielle Verletzung des strengen Aliasings zu sein scheint. Ich war dabei, die Dokumentation zu suchen, um diese Behauptung zu unterstützen. Könnten Sie bitte einen Link einfügen? – sjsam

2

Es ist schwer für den Compiler, die Verletzung bei der Kompilierung zu fangen, es sei denn, Sie vergeben einen neuen Wert durch Dereferenzierung in einen anderen Typ, wie unten gezeigt. Wenn Sie Ihren Code wie unten gezeigt ändern, erhalten Sie die Warnung, die Sie erwartet haben.

int main(void) 
{ 
    int n = 74; 
    //int * pn = &n; 

    //short * sp; 

    //sp = (short *)&n; // <-- bad 
    //sp = (short *)pn; // <-- fine 

    *((short*)&n) = 4; 
    printf("%d\n", n); 

    return 0; 
} 

Diese Frage zeigt das exakt gleiche Problem und bietet noch mehr Details. GCC: accuracy of strict aliasing warnings

Die andere Antwort von AnT mit dieser Aussage begann: „Es ist nicht das Casting ist per se, die streng-Aliasing verletzt, ist es der nachfolgende ungültig lvalue Zugriff (Speicher Umdeutung), die es verletzt ist.“ .... Das ist richtig. Mein Beispiel versucht einen lvalue-Zugriff, der die Regel verletzt, sodass Sie die Warnung erhalten.

Verwandte Themen