У меня здесь особая проблема, которая происходит как с VS2005, так и с 2010. У меня есть цикл for, в котором вызывается встроенная функция, по сути что-то вроде этого (С++, только для иллюстративных целей):
inline double f(int a)
{
if (a > 100)
{
// This is an error condition that shouldn't happen..
}
// Do something with a and return a double
}
А затем цикл в другой функции:
for (int i = 0; i < 11; ++i)
{
double b = f(i * 10);
}
Теперь происходит то, что в отладочной сборке все работает нормально. В релизной сборке со всеми включенными оптимизациями это, судя по дизассемблированию, скомпилировано так, что i
используется напрямую без * 10
, а сравнение a > 100
превращается в a > 9
, а я предполагаю, что должно быть a > 10
. Есть ли у вас какие-либо сведения о том, что может заставить компилятор думать, что a > 9
- правильный путь? Интересно, что даже незначительное изменение (например, отладочная распечатка) в окружающем коде заставляет компилятор использовать i * 10
и сравнивать это с буквальным значением 100.
Я знаю, что это несколько расплывчато, но я был бы признателен за любую старую идею.
ИЗМЕНИТЬ:
Вот, надеюсь, воспроизводимый случай. Я не считаю его слишком большим, чтобы вставлять сюда, так что вот:
__forceinline int get(int i)
{
if (i > 600)
__asm int 3;
return i * 2;
}
int main()
{
for (int i = 0; i < 38; ++i)
{
int j = (i < 4) ? 0 : get(i * 16);
}
return 0;
}
Я протестировал это с VS2010 на своей машине, и, похоже, он ведет себя так же плохо, как и исходный код, с которым у меня проблемы. Я скомпилировал и запустил это с пустым шаблоном проекта С++ по умолчанию в среде IDE в конфигурации выпуска. Как видите, брейк ни в коем случае нельзя делать (37 * 16 = 592). Обратите внимание, что удаление i < 4
делает эту работу такой же, как и в исходном коде.