У меня есть этот небольшой фрагмент кода (это минимальный рабочий пример проблемы, который у меня есть):
#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;
}
Этот код должен выполнять эксклюзивные или два 32-байтовых буфера памяти (концептуально это должно делать a = a ^ b
). Так как 0xAA ^ 0xBB = 0x11, он должен печатать "11" тридцать два раза.
Моя проблема заключается в том, что когда я компилирую это в MinGW-GCC (Windows), это отлично работает в режиме отладки (без оптимизации), но с SIGILL наступает через середину цикла xorBuffer, когда оптимизация начинается с -O3. Кроме того, если я поставлю printf в оскорбительном цикле, он будет работать отлично. Я подозреваю, что повреждение стека, но я просто не вижу, что я делаю неправильно здесь.
Попытка отладки с GDB с включенными оптимизациями - это потерянная причина, так как все GDB показывает, что "переменная оптимизирована" для каждой переменной (и, конечно, если я попытаюсь распечатать переменную, она внезапно начнет работать).
Кто-нибудь знает, что здесь происходит? Я слишком долго занимался этой проблемой, и мне действительно нужно исправить это правильно, чтобы двигаться дальше. Я предполагаю, что мне не хватает какого-либо фундаментального знания указателя C, но для меня код выглядит правильно. Это может быть из инкремента буфера, но, насколько я знаю, sizeof(unsigned char) == 1
, поэтому он должен проходить каждый байт один за другим.
Для чего это стоит, код работает даже с оптимизациями на GCC на моем Linux-сервере.
Итак... какая сделка здесь? Спасибо!
В соответствии с запросом выводится сборка всей программы:
С -O2: clicky
С -O3: clicky
Я наблюдаю это поведение на GCC 4.6.2 (работает с MinGW)