Ayuda a corregir o ignorar la advertencia de alias en gcc

2

Tengo un problema al trabajar con la placa de demostración TI / Stellaris EK-LM3S6965 y el software asociado, específicamente el controlador de pantalla OLED. Mi problema no es que no funcione, es que principalmente funciona. Excepto por esta sección:

//
// Clear out the buffer used for sending bytes to the display.
//
*(unsigned long *)&g_pucBuffer[0] = 0;  //Line 438
*(unsigned long *)&g_pucBuffer[4] = 0;  //Line 439

lo que hace que gcc se queje:

  

rit128x96x4.c: 438: advertencia:   desreferenciación puntero tipo punted será   romper las reglas de aliasing estrictas.

El problema se produce porque g_pucBuffer se declara como una matriz de caracteres:

//*****************************************************************************
//
// Buffer for storing sequences of command and data for the display.
//
//*****************************************************************************
static unsigned char g_pucBuffer[8];

pero lo estamos accediendo como un largo (32 bits, 4 caracteres) y, por lo tanto, borramos la matriz en 2 líneas de código en lugar de 8. La unidad de control es un procesador de 32 bits, por lo que debería hacerlo en 2 ciclos después de la configuración. En realidad, usa 4 instrucciones, en lugar de la posible instrucción de 1 almacén múltiple en 2 ciclos, pero en este punto estoy más que contento con el rendimiento del compilador (es una arquitectura bastante nueva y el compilador tiene solo unos meses).

Pero, cuando escribo cada byte secuencialmente a 0,

g_pucBuffer[0] = 0;
g_pucBuffer[1] = 0;
g_pucBuffer[2] = 0;
g_pucBuffer[3] = 0;
g_pucBuffer[4] = 0;
g_pucBuffer[5] = 0;
g_pucBuffer[6] = 0;
g_pucBuffer[7] = 0;

hace cada escritura como una sola instrucción. Lo sé, son 4 ciclos, pero quiero hacer esto bien, y creo que tengo un código inteligente y seguro. Es más un problema personal ahora. Tengo la optimización completa activada, pero no puedo entender que realmente quiero que estos 64 bits sean 0 tan simple como sea posible.

Sin embargo, lo que la advertencia quiere que haga es acceder a las variables como caracteres, porque estoy cruzando los límites de bytes (escribiendo g_pucBuffer [0, 1, 2 y 3] en un solo paso). Sé que están alineados con las palabras, sé que el código funciona en el original, pero quiero que desaparezca la advertencia.

¿Cómo puedo hacer que gcc ignore este problema de conversión / aliasing específico o lo haga correctamente?

    
pregunta Kevin Vermeer

5 respuestas

4

¿Puede declarar su variable como una unión de una matriz de bytes y una matriz larga?

No sé si esto es más "legal" que su código original sin una lectura cuidadosa de la especificación, pero podría valer la pena investigarlo.

    
respondido por el John Burton
5

Un lanzamiento intermedio a (vacío *), luego lanzado a (largo *) puede deshacerse de la advertencia. Verifiqué esto antes hoy (al menos con gcc 3.4.5), que

*(long*)(void*)&buffer[0] = 0;

descompone al compilador de la idea de que el cielo se caerá si lanzas & buffer [0] a (largo *).

Yo diría que esto es mejor que usar una opción de aliasing -fno-strict, ya que -aliasing -fno-strict tendrá un efecto global, mientras que la conversión intermedia se puede usar caso por caso, y es explícitamente obvio en su fuente real donde ha resuelto el problema.

    
respondido por el JustJeff
3

Personalmente creo que las advertencias del compilador están ahí por una razón. Deshabilitarlos o ignorarlos (como algunas de las otras respuestas parecen recomendar) es una mala idea. -fno-strict-aliasing previene un montón de otras optimizaciones, al final, probablemente perderá mucho más rendimiento que los 4 ciclos que ahorra haciendo el pirateo del código C.

    
respondido por el davr
2

¿No funcionaría -fno-strict-aliasing?

    
respondido por el cesare
1

Respuesta rápida: elimine -Werror de su Makefile. Solo con esta opción habilitada, la advertencia se tratará como un error.

    
respondido por el Toby Jaffey

Lea otras preguntas en las etiquetas