Целочисленное значение изменяется при выходе из блока препроцессора

У меня есть кусок кода, где кажется, что переменная изменяется в конце блока кода препроцессора.

int initialKeyCount;
#if(DEBUG)
//          int initialKeyCount = _root.CountAllKeys();
      initialKeyCount = 20000;
#endif
      currNode = currNode.EnsureDegreeKeysPresent(parent); //initialKeyCount = 19969 here
#if(DEBUG)
      int currentKeyCount = _root.CountAllKeys();
      Debug.Assert(initialKeyCount == currentKeyCount,
               string.Format("EnsureDegreeNodesPresent changed the node count from {0} to {1}.", initialKeyCount, currentKeyCount));
#endif

При выполнении этого в отладчике initialKeyCount = 19969 после предположительного присвоения 20000. Я немного поиграл с этим и обнаружил, что назначение initialKeyCount правильно внутри первого блока препроцессора, но как только код покидает первый препроцессор block значение волшебным образом меняется на 19969.

Это поведение одинаково независимо от того, объявлена ​​ли переменная внутри или снаружи первого блока препроцессора. Значение остается 19969 внутри второго блока препроцессора.

Назначения, сделанные в блоке препроцессора, не определены вне этого блока? Это кажется неправильным, но, похоже, это то, что здесь происходит.


person ScottS    schedule 06.01.2009    source источник
comment
Похоже на ошибку для меня. Имеет ли он те же значения, если вы запустите его без отладчика и выведете значения на экран?   -  person Toon Krijthe    schedule 06.01.2009


Ответы (5)


Похоже, Visual Studio запуталась. Попробуйте эти шаги по порядку

  1. Используйте команду «Очистить».
  2. Перезапустите Visual Studio.
  3. Удалите все DLL и EXE, которые хотя бы отдаленно похожи на вашу программу.
  4. Дважды проверьте каждую папку BIN и OBJ, чтобы убедиться, что вы ничего не пропустили.
  5. Найдите на всем жестком диске любые DLL и EXE-файлы, которые хотя бы отдаленно похожи на вашу программу, и удалите их тоже.

Раньше я видел это раз в неделю в ИТ-компании, в которой работал. Обычно бывает, когда у тебя несколько копий одного и того же проекта, но я видел и без этого.

person Jonathan Allen    schedule 06.01.2009
comment
Простой перезапуск VS не решил проблему, но пара дней и перезагрузка, похоже, заставили ее уйти. - person ScottS; 10.01.2009

Такое поведение очень похоже на то, что отладчик запускает код, не соответствующий исходному коду, который вы редактируете. Вы абсолютно уверены, что ваши изменения в исходном коде распространяются на код, который вы запускаете?

Блоки препроцессора не связаны с синтаксисом языка. Итак, вы правы, говоря, что блоки препроцессора не влияют на область определения переменных.

person Greg Hewgill    schedule 06.01.2009

Я согласен с Грегом Хьюгиллом — я уже видел подобное раньше.

Кроме того, найдите сборку, которую использует отладчик, и откройте ее с помощью Reflector. Разборка должна дать вам лучшее представление о том, что на самом деле происходит.

person Andrew Kennan    schedule 06.01.2009

Столкнувшись с чем-то подобным, посмотрите на это на уровне сборки.

В то время как ассемблер — это то, что вы почти никогда не будете кодировать в наши дни, его НЕОБХОДИМО знать, чтобы проследить такие загадки.

person Loren Pechtel    schedule 06.01.2009

Вещи становятся все более и более странными. Я воспользовался приведенными выше предложениями и изучил код с помощью Reflector и дизассемблирования, предоставленного отладчиком, оба выглядят так, как и следовало ожидать. Я немного изменил код, чтобы четко показать «волшебное» изменение переменной.

Новый код

int initialKeyCount;
#if(DEBUG)
//          int initialKeyCount = _root.CountAllKeys();
      initialKeyCount = 20000;
      initialKeyCount++;
      initialKeyCount = initialKeyCount;
#endif
      currNode = currNode.EnsureDegreeKeysPresent(parent);
#if(DEBUG)
      int currentKeyCount = _root.CountAllKeys();
      Debug.Assert(initialKeyCount == currentKeyCount,
               string.Format("EnsureDegreeNodesPresent changed the node count from {0} to {1}.", initialKeyCount, currentKeyCount));
#endif

Разборка вышеперечисленного

int initialKeyCount;
#if(DEBUG)
//          int initialKeyCount = _root.CountAllKeys();
      initialKeyCount = 20000;
00000094  mov         dword ptr [ebp-50h],4E20h 
      initialKeyCount++;
0000009b  inc         dword ptr [ebp-50h] 
      initialKeyCount = initialKeyCount;
0000009e  nop              
#endif
      currNode = currNode.EnsureDegreeKeysPresent(parent);
0000009f  mov         edx,dword ptr [ebp-48h] 
...

Используя окно памяти, я смотрел значение в ebp-0x50. Когда IP

на 00000094 значение равно 0x0
на 0000009b значение равно 0x4e20
на 0000009e значение равно 0x4e21
на 0000009f значение равно 0x4e01

Я признаю, что прошло много времени с тех пор, как я писал код на ассемблере, но я вполне уверен, что nop не должен писать в память. :)

Очевидно, выполняется какой-то код, который отладчик не отображает. Кто-нибудь знает, есть ли что-то в том, как я использовал препроцессор, который вызывает это, или это просто ошибка?

person ScottS    schedule 06.01.2009