Странное поведение с переменными в релизе по сравнению Отладочные сборки

#c #visual-studio-2010

#c #visual-studio-2010

Вопрос:

У меня есть проект C в Visual Studio 2010.

Я просто пытаюсь сравнить две строки друг с другом, но я вижу совершенно другое поведение в моей сборке Release. Отладочная сборка работает так, как ожидалось. Я не вносил никаких изменений в оптимизации, кроме значений по умолчанию, которые устанавливает Visual Studio 2010.

Вот мой код:

 wchar_t validCRC[] = L"0xd07153b9";
wchar_t thisCRC[] = L"0xd07153b9"; // this is calculated on the fly but I get same behavior if I set it manually. i also tried setting these both to L"hello" and got same result

int cmp = 0;
cmp = wcscmp(validCRC, thisCRC); // if I put a breakpoint here, the visual studio debugger says 'cmp' is not in scope. 
pLog->Write("value of cmp: %d", cmp); // in both DEBUG and RELEASE, this prints "value of cmp: 0"

if (cmp == 0)
{ // yet for some reason, the DEBUG build follows this path
    return true;
}
else
{ // the RELEASE build follows this path
    return false;
}
  

Комментарии:

1. Какое значение cmp, если не 0?

2. Это не настоящий код, не так ли? Опубликуйте что-нибудь минимальное, что воспроизводит вашу проблему.

3. Возможно ли, что вычисленный thisCRC не завершается с нулевым завершением?

4. @ Dabbler — я подтвердил, что значение cmp равно 0 в обеих сборках. @ K-ballo — я не совсем уверен, что вы ищете. Вы хотите использовать void main() вокруг него? @ ThierryFranzetti — но они оба устанавливаются одинаково, используя L»stringhere»

5. Тогда проблема связана с оптимизацией, выполняемой компилятором. В сборке release (т. Е. С оптимизацией) отладчик часто неправильно отображает значения переменных, и при пошаговом выполнении может показаться, что точка выполнения находится там, где ее на самом деле нет. Это связано с тем, что корреляция между строками исходного кода и сгенерированным машинным кодом гораздо менее прямая, чем в неоптимизированном коде.

Ответ №1:

Сборки Release оптимизированы, поэтому отладчику часто бывает сложно выдавать вам значения отдельных переменных, особенно локальных переменных, которые часто являются сохраненными регистрами, которые используются для чего-то еще несколькими инструкциями позже.

Вот почему вы используете отладочную сборку для отладки и сборку release для сборки, которую вы выпустите.

Если вам действительно нужно отладить проблему, которая возникает только в сборке release (очень часто причиной являются неинициализированные переменные), вы можете использовать специфичную для компилятора #pragma только для деоптимизации определенных частей, или вы можете деоптимизировать определенные файлы, или вы можете использовать инструкции printf.

РЕДАКТИРОВАТЬ: когда вы говорите «следовать» этому пути, вы, вероятно, имеете в виду, что так оно и выглядит, когда вы проходите через него в отладчике. Опять же, код оптимизирован, поэтому сборка не соответствует исходному коду. Возвраты, в частности, часто оптимизируются так, что в сборке есть только одна фактическая инструкция возврата. Таким образом, пошаговое выполнение кода в сборке release не является надежным способом определить, что происходит.

Еще раз, правильный способ отладки сборок release — использовать printfs и другие механизмы. Вы все равно можете использовать отладчик, чтобы получить общее представление о том, что происходит, но вы не можете полагаться на подобные детали.

Комментарии:

1. Использование printf подтверждает, что cmp равен 0 в обеих сборках

2. Точно! printf не лжет. Значения переменных, однако, выполняются (в сборках release). В некоторых средах в некоторых отладчиках вы можете видеть совершенно неправильные значения. Итак, еще раз, если вы хотите что-то отладить в отладчике, используйте сборку debug . Для сборки release вам понадобятся другие средства отладки, такие как printf.

3. Хорошо, я увидел ваше редактирование, поэтому отредактировал свой ответ. Опять же: отладчик в сборках release обязательно предоставит вам вводящую в заблуждение информацию. Результат — это то, что имеет значение.

Ответ №2:

Попробуйте напечатать значение вместо того, чтобы полагаться на отладчик в режиме Release. Оптимизатор очень агрессивен, и ваши символы могут указывать на код, который оптимизируется.

Комментарии:

1. Я сделал, и в обоих случаях значение cmp равно 0