В настоящее время мы разрабатываем приложение для MCU msp430 и сталкиваемся с некоторыми странными проблемами. Мы обнаружили, что объявление массивов в области видимости после объявления «нормальных» переменных иногда вызывает поведение, которое кажется неопределенным. Как это:
foo(int a, int *b);
int main(void)
{
int x = 2;
int arr[5];
foo(x, arr);
return 0;
}
foo передается указатель в качестве второй переменной, которая иногда не указывает на массив arr . Мы проверяем это с помощью одного пошагового выполнения программы и видим, что значение переменной arr array-as-a-pointer в основной области видимости не совпадает со значением переменной-указателя b в области видимости foo. И нет, это не совсем воспроизводимо, мы только что наблюдали это поведение время от времени.
Это можно наблюдать даже до того, как будет выполнена одна строка функции foo, переданный параметр-указатель (b) просто не указывает на адрес, к которому относится arr.
Изменение примера, похоже, решает проблему следующим образом:
foo(int a, int *b);
int main(void)
{
int arr[5];
int x = 2;
foo(x, arr);
return 0;
}
Есть ли у кого-нибудь какие-либо замечания или подсказки относительно того, почему мы испытываем такое поведение? Или похожий опыт? Руководство по программированию MSP430 указывает, что код должен соответствовать спецификации ANSI C89. и поэтому мне было интересно, если он говорит, что массивы должны быть объявлены до переменных, не являющихся массивами?
Любой вклад в это будет приветствоваться.
Update
@ Адам Шимке и Томлогик:
Мне интересно, что C89 указывает на различные способы инициализации значений в объявлениях. Вам разрешено написать что-то вроде:
int bar(void)
{
int x = 2;
int y;
foo(x);
}
И если да, то как насчет:
int bar(int z)
{
int x = z;
int y;
foo(x);
}
Это разрешено? Я предполагаю, что следующее должно быть незаконным C89:
int bar(void)
{
int x = baz();
int y;
foo(x);
}
Заранее спасибо.
Обновление 2
Задача решена. В основном мы отключаем прерывания перед вызовом функции (foo) и после объявления переменных. Мы смогли воспроизвести проблему на простом примере, и решение, по-видимому, заключается в добавлении оператора _NOP () после вызова прерывания отключения.
Если кому-то интересно, могу выложить полный пример, воспроизводящий проблему, и исправить?
Спасибо за все комментарии по этому вопросу.