пятница, 29 мая 2009 г.

Бывет и такое...

Казалось бы проблемы из-за сравнения знаковых и беззнаковых значений давно известны и обходятся опытными разработчиками. Однако, разработчики компилятора Microsoft C++, который входит в состав Visual Studio 2008 SP1 сделали такую ошибку, которая и была (не без удивления) обнаружена у нас в компании. Код, который позволяет воспроизвести эту ошибку приведен ниже:
#include <iostream>
using namespace std;

int main()
{
for ( int k = -4; k < -1; k++ ) {
unsigned long kkk = (k+4)*8+1;
bool jjj = kkk < 256;
if ( jjj == false ) cout << "Impossible!!!" << endl;
}
}
Если скомпилировать такой код с ключом /O2(cl /EHsc /O2 main.cpp), то будет выведен текст, который не должен быть выведен. Если без ключа оптимизации(cl /EHsc main.cpp), то текст не будет выведен.

Проблема тут в том, что компилятор оптимизурет выражение (k+4)*8+1 < 256 до k < 28, забывая что k может принимать отрицательные значения и результат сравнения проверяет командой, которая знак не учитывает.

Нечасто приходится сталкиваться с такими ошибками и страшно подумать, где в коде это может проявится. Последить за судьбой этого бага в багтрекере Майкрософт можно тут.

Комментировать в ВКонтакте