之前在C“正常”变量数组的声明?
-
22-09-2019 - |
题
我们目前正在开发用于MSP430系列单片机的应用程序,并遇到了一些奇怪的问题。我们发现,宣称阵列withing“正常”变量的声明后,范围有时会导致什么似乎是未定义的行为。像这样:
foo(int a, int *b);
int main(void)
{
int x = 2;
int arr[5];
foo(x, arr);
return 0;
}
FOO传递指针,作为第二变量,该<强>有时强>不指向 ARR 阵列。我们通过程序由单步执行验证这一点,并看到在主范围的ARR阵列作为一种指针变量的值是不相同的FOO范围的B指针变量的值。不,这是不是真的reproduceable,我们只是在观察了一会儿,一旦这种行为。
此执行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规范。所以我想知道如果它说,阵列已到之前非数组变量声明?
在此的任何输入,将不胜感激。
结果
<强>更新强>
@Adam Shiemke和tomlogic:
我想知道什么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 强> 问题解决了。基本上,我们在那里调用函数(富)之前和变量声明后,不能中断。我们在那里能够再现一个简单的例子的问题,而解决方案似乎是禁止中断通话后添加_NOP()语句。
如果任何人的爱好,我可以张贴完整的示例再现问题,和固定?
感谢您的所有输入上这一点。
解决方案
您应该能够确定它是否是基于所产生的汇编代码编译器故障。是国内组装不同的,当你改变的变量声明的顺序?如果您的调试器允许您通过组装尝试单步执行。
如果你找到一个编译器缺陷,另外,检查你的优化。我已经看到这样由优化引入错误。
其他提示
,看起来像一个编译错误。
如果你用你的第一个例子(有问题的),写你的函数调用为foo(x, &arr[0]);
,你看到同样的结果?怎么样,如果你喜欢初始化的int arr[5] = {0};
阵列?这些都不应该改变什么,但如果他们这样做将在编译器错误提示。
在更新的问题:
基本上,我们在那里调用函数(
foo
)之前和变量声明之后禁止中断。我们在那里能够再现一个简单的例子的问题,而解决方案似乎是禁止中断通话后添加_NOP()
声明。
听起来好像关闭中断固有/功能/宏(或然而中断被禁止)可能会引起的指令是“跳过”或东西。我会调查这是否是编码/正常工作。
两个例子都看要符合C89我。应该有未访问超出阵列的边界的行为假设foo
没有可观察到的差异。
有关C89,变量需要在范围的开始的列表之前的任何分配声明。 C99允许你混合分配的声明。所以:
{
int x;
int arr[5];
x=5;
...
是法律风格C89。我很惊讶你的编译器没有把对某种错误的,如果它不支持C99。
假设真正的代码要复杂得多,继承人有些事情我会检查,记住他们的猜测:
你能满溢之际堆栈?如果是的话这会是“堆防御”的一些神器由编译器/ UC?是否可预测的内存范围内不正确的值FOO下跌呢?如果这是否范围具有任何意义(堆栈等的内部)?
是否mcu430具有RAM和ROM寻址不同的范围?也就是说,对于16位的RAM,而程序地址空间的24位地址空间? PIC的有例如这样的架构。如果是的话这将是可行的ARR是越来越分配为ROM(24位)和函数需要一个指向RAM(16位)的代码将工作时的ARR中的地址空间中的第16位的被分配但砖如果高于该范围的。
也许你在你的程序的一些地方非法存储器写从而破坏你的筹码。
你看看拆卸?