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

StackOverflow https://stackoverflow.com/questions/414986

Вопрос

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

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 является правильным внутри первого блока препроцессора, но как только код покидает первый блок препроцессора, значение волшебным образом меняется на 19969.

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

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

Это было полезно?

Решение

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

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

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

Другие советы

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

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

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

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

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

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

Все становится все более и более странным.Я воспользовался приведенными выше предложениями и изучил код с помощью 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 не должен записывать данные в память.:)

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top