Странная ошибка при выполнении кода на C в MSVC 2005 - PullRequest
1 голос
/ 18 марта 2009

Я столкнулся со следующей причудливой ошибкой.

У меня есть рабочая область в MSVS2005 всего кода C. Я объявил глобальную переменную в одном файле C. (file1.c) В этом файле есть функция main (), в которой я инициализирую значение этой переменной = 0. В другом файле C (file2.c). Из main есть вызов функции (func1 в file2.c), который устанавливает значение этой глобальной переменной равным 1. В file2.c я объявил глобальную переменную как "extern .." и получил к ней доступ. Но что я заметил, так это то, что в момент основной функции, когда выполнение кода входит в функцию func2, в окне просмотра я вижу, что адрес самой этой глобальной переменной изменяется на совершенно другой адрес (в окне просмотра я наблюдаю & переменная). В результате, когда значение этой переменной установлено в 1, оно записывает значение 1 в совершенно другой адрес памяти. Поэтому, когда позже я использую эту переменную для проверки условия if (if variable == 1), она по-прежнему показывает значение 0 и не удовлетворяет условию if и не принимает этот путь кода, где ожидалось, что он принял этот путь.

Обход: Я объявил эту переменную в одной из моих существующих глобальных структур, а затем получил доступ к этой переменной для выполнения тех же операций; код работает как положено.

Так что может быть объяснением ошибки, которая вызывает изменение адреса глобальной переменной, если она объявлена ​​как глобальная в некотором C-файле? Не имеет значения, в каком * .c файле я его объявляю и в какой файл я обращаюсь к нему с помощью «extern», результатом является то же самое изменение адреса глобальной переменной и последующая ошибочная операция. Опция оптимизации не включена.

Спасибо

-AD

Ответы [ 4 ]

1 голос
/ 18 марта 2009

Можно только догадываться, фактически не видя код, но здесь есть 2 возможности:

  1. глобальная переменная скрывается локальной переменной либо в main(), либо в func2() (или, может быть, func1() - вопрос упоминает func1(), но я подозреваю, что это опечатка - вот почему вырезание и вставка кода довольно важно);
  2. вы ошибочно объявляете глобальную переменную как static в file1.c и имеете инициализатор в объявлении extern в file2.c. Наличие инициализатора в объявлении extern приведет к тому, что это объявление также будет определением.
0 голосов
/ 18 марта 2009

Если переменная имеет другой адрес в разных единицах перевода, вы видите не одну, а как минимум две переменные с одинаковым именем.

Наиболее распространенная причина: вы могли случайно объявить локальную переменную в стеке с тем же именем. Проверьте свой код для этого. Если переменные действительно глобальные, компоновщик должен пожаловаться, если две единицы перевода содержат один и тот же символ.

Если это не помогает, и если вы все еще видите несколько копий одного и того же символа-символа, вероятно, лучше взглянуть на файл карты (это можно включить в настройках компоновщика).

Все внешние символы перечислены там с их именем, адресом и (что наиболее важно в вашем случае) объектом-файлом, который их содержал.

Адреса в файле карты могут быть просто смещениями. В этом случае сделайте все свои вычисления относительно символа, который, как известно, существует только один раз. для этого может быть полезна точка входа main ().

0 голосов
/ 18 марта 2009

Возможно, опечатка или что-то похожее в вашем коде. Попробуйте это рабочее демо:

file1.c

int variable;
void fun1(int k);

int main()
{
    printf("%d\n", variable);
    fun1(4);
    printf("%d\n", variable);
}

file2.c

extern int variable;

void fun1(int k)
{
    variable = k;
}

Выход:

0
4

Для компиляции:

cl.exe file1.c file2.c
0 голосов
/ 18 марта 2009

Возможно, попробуйте объявить его энергозависимым (не уверен, действительно ли это даже для глобальных переменных) и отключите все оптимизации компилятора на случай, если он каким-то образом усложнится.

...