tengo este pequeño fragmento de código (este es un ejemplo de trabajo mínima del problema que tengo):comportamiento extraño con optimizaciones habilitadas
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void xorBuffer(unsigned char* dst, unsigned char* src, int len)
{
while (len != 0)
{
*dst ^= *src;
dst++;
src++;
len--;
}
}
int main()
{
unsigned char* a = malloc(32);
unsigned char* b = malloc(32);
int t;
memset(a, 0xAA, 32);
memset(b, 0xBB, 32);
xorBuffer(a, b, 32);
printf("result = ");
for (t = 0; t < 32; t++) printf("%.2x", a[t]);
printf("\n");
return 0;
}
Este código se supone que debe realizar la o-exclusiva de dos 32- Buffers de memoria de bytes (conceptualmente, esto debería hacer a = a^b
). Como 0xAA^0xBB = 0x11, debería imprimir "11" treinta y dos veces.
Mi problema es que cuando compilo esto en MinGW-GCC (Windows), esto funciona perfectamente en modo de depuración (sin optimizaciones) pero se bloquea con un SIGILL a mitad del ciclo xorBuffer cuando las optimizaciones a partir de -O3 están habilitadas. Además, si pongo un printf en el bucle ofensivo, funcionará perfectamente de nuevo. Sospecho que hay corrupción en la pila, pero no veo lo que estoy haciendo mal aquí.
intentando depurar con GDB con optimizaciones habilitadas es una causa perdida como muestra toda BGF me está "optimizado variable de salida" para todas las variables (y, por supuesto, si lo intento y printf a cabo una variable, que va a trabajar pronto)
¿Alguien sabe qué diablos está pasando aquí? He invertido demasiado tiempo en este tema, y realmente necesito solucionarlo adecuadamente para seguir adelante. Supongo que me falta algo del conocimiento fundamental del puntero C, pero a mí el código parece correcto. Podría ser desde el incremento del búfer, pero hasta donde yo sé, sizeof(unsigned char) == 1
, por lo que debería pasar por cada byte uno por uno.
Por lo que vale, el código funciona incluso con optimizaciones en GCC en mi cuadro de Linux.
Entonces ... ¿cuál es el problema aquí? ¡Gracias!
Conforme a lo solicitado, la salida de montaje de todo el programa:
Con O2: clicky
Con -O3: clicky
que observar este comportamiento en GCC 4.6.2 (que se ejecuta con MinGW)
¿Qué hay de usar 'O2'? 'O3' es bastante arriesgado. SIGILL significa - señal, causada por instrucción ilegal. Parece un error de compilación para mí. O me estoy perdiendo algo. –
Esto funciona perfecto en mi gcc 4.4.3. Si nadie nota nada, puede intentar mostrarnos el código de ensamblaje, producido por gcc, en ambos casos - con 'O3' y' O2' (si funciona bien; de lo contrario, menor nivel de optimización) –
@KirilKirov Este error fue descubierto originalmente en una biblioteca de alto rendimiento, por lo que bajar a O2 no es realmente la mejor solución para nosotros; por supuesto, si se trata de un error del compilador bajaremos a O2 hasta que se emita una solución. Publicaré el ensamblaje producido sin optimizaciones y con -O3. – Thomas