tiempo submuestreo sobremuestreo nyquist muestreo funcion frecuencia estadistica ejemplos efecto c gcc c99 strict-aliasing

submuestreo - GCC: exactitud de las advertencias estrictas de aliasing



nyquist (4)

Espero que en O3 el compilador decida que, dado que sabe que las variables de diferentes tipos no pueden ser alias , nunca se usa sp . Por lo tanto, elimina sp del programa y no se produce ningún error.

Ya sea que, o dado que l es un valor conocido, se está convirtiendo en una constante para que lo utilice printf. Todavía tendrá almacenamiento porque se toma su dirección, pero ese almacenamiento nunca se escribe hasta donde se sabe.

Estoy tratando de verificar parte de mi código para ver si hay violaciones estrictas de aliasing, pero parece que me he perdido algo al tratar de entender la regla de aliasing estricta.

Imagina el siguiente código:

#include <stdio.h> int main( void ) { unsigned long l; l = 0; *( ( unsigned short * )&l ) = 1; printf( "%lu/n", l ); return 0; }

Ejemplo clásico y básico. Con GCC 4.9 ( -Wall -fstrict-aliasing -Wstrict-aliasing -O3 ), en realidad informa del error:

dereferencing type-punned pointer will break strict-aliasing rules

Pero lo siguiente compila bien:

#include <stdio.h> int main( void ) { unsigned long l; unsigned short * sp; l = 0; sp = ( unsigned short * )&l; *( sp ) = 1; printf( "%lu/n", l ); return 0; }

En mi entendimiento, el segundo ejemplo también viola la regla de aliasing de estructura.
Entonces, ¿por qué se compila? ¿Es un problema de precisión en GCC o me he perdido algo con un alias estricto?

También encontré el siguiente tema: ¿Por qué no se generan advertencias de alias estricto para este código?

La -Wstrict-aliasing=2 con -Wstrict-aliasing=2 o -Wstrict-aliasing=3 no hace ninguna diferencia.
Pero -Wstrict-aliasing=1 informa el error en el segundo ejemplo.

La documentación de GCC dice que el nivel 1 es el menos preciso y puede producir muchos falsos positivos, mientras que el nivel 3 es el más preciso ...

Entonces, ¿qué está pasando aquí? ¿Un problema con mi propia comprensión o un problema con GCC?

Pregunta extra

Normalmente prefiero Clang / LLVM en lugar de GCC para mis proyectos, pero parece que Clang no emite ninguna advertencia sobre el alias estricto.
¿Alguien sabe por qué?
¿Se debe a que no puede detectar infracciones o porque no sigue la regla al generar código?


Mi interpretación de la situación:

  1. *( ( unsigned short * )&l ) = 1; Es más fácil de atrapar, porque la violación está en una sola línea. Así que siempre está atrapado.

  2. Con la optimización, también se captura la segunda variación. Después de la optimización, es tan simple como el primero.

  3. Sin optimización, -Wstrict-aliasing=1 , que es más lento que el predeterminado, lo atrapa. Esto se debe a que trata la conversión en sí misma como una violación, incluso sin la desreferencia (eliminar la desreferencia y ver). Esta lógica simplista es rápida, pero conduce a falsos positivos.


No hay nada inherentemente malo con

sp = ( unsigned short * )&l;

Por lo que sabe el compilador, simplemente puede volver a colocar el puntero al tipo correcto.

Tampoco hay nada inherentemente malo con

*( sp ) = 1;

Es la combinación de los dos lo que está mal.

El compilador simplemente no puede juntar los dos para decirle que la combinación es problemática (es imposible en el caso general, y no es tan fácil en este caso en particular).

Pero

*( ( unsigned short * )&l ) = 1;

es mucho más fácil de detectar, y por lo tanto el compilador hace todo lo posible para hacerlo.


Su comprensión es correcta. El análisis de alias es generalmente complicado y en este caso, aparentemente, el mero uso de un puntero temporal entre el reparto y la desreferencia fue suficiente para desecharlo. Sorprendentemente, GCC 4.8.2 hace un mejor trabajo en este código, advirtiendo en -Wstrict-aliasing=2 así como en el nivel 1, por lo que esta es una regresión.

En cuanto a clang, simplemente no tiene actualmente la posibilidad de advertir sobre violaciones de aliasing. Aprovecha absolutamente la regla en la optimización. Para ver esto en acción, tome este ejemplo directamente del estándar C (N1570 §6.5.2.3 9))

struct t1 { int m; }; struct t2 { int m; }; int f(struct t1 *p1, struct t2 *p2) { if (p1->m < 0) p2->m = -p2->m; return p1->m; }

Si p1 y p2 apuntan a la misma estructura, Clang (y GCC) sin embargo devolverán el valor de p1->m antes de la negación, ya que pueden asumir que p2 no tiene alias p1 y, por lo tanto, la negación anterior nunca afecta el resultado. Aquí está el ejemplo completo y la salida con y sin -fstrict-aliasing . Para obtener más ejemplos, consulte here y lo que cada programador de C debería saber sobre el comportamiento indefinido ; Las optimizaciones estrictas de alias son el tema final de la publicación introductoria.

En cuanto a cuándo se implementarán las advertencias, los desarrolladores están tranquilos , pero se mencionan en la suite de pruebas de -Wstrict-aliasing=X , que enumera -Wstrict-aliasing=X debajo del título (énfasis mío)

Estas banderas no están implementadas actualmente ; prueba de que los emitimos de todos modos.

Por lo que parece probable que suceda en algún momento.