我有一个c++程序,它的方法如下所示:
int myMethod(int* arr1, int* arr2, int* index)
{
arr1--;
arr2--;
int val = arr1[*index];
int val2 = arr2[val];
return doMoreThings(val);
}在启用优化(/O2)的情况下,不会执行第一个指针减少的第一行。我正在同时调试优化的和非优化的构建,优化的构建步骤通过减少,而非优化的程序执行它。这在以后使用arr*index访问数组时会产生明显的行为差异。
更新
正如@stefaanv所指出的,如果编译器更改为递减的访问索引(它似乎是这样做的),则编译器确实可以省略该减量。因此,省略的减少并不是导致行为差异的原因。相反,在矩阵的使用中有一些东西导致了它。
再看一看,我把范围缩小到一个包含执行矩阵乘法的嵌套循环的方法。该方法的部分内容如下:涉及3个数组: a、wa和t。在该方法的开头,f2c转换器使用了一个递减,以便在fortran中为6乘6的数组是c中的平面double[36]。但是为了能够使用旧的索引,它将数组指针按矩阵中的列数向后移动。
通常,在这个f2c翻译的程序中,平面数组是以&someArray[1]的形式传递的,方法从每一个数组的递减开始。@Christoph指出,这应该是有效的,因为数组的递减永远不会超出其声明的范围。
在这种方法中,传入的数组不是作为指向元素的指针传递到数组&someArray[1]中,而是在这里,数组是以固定大小声明的本地静态数组,例如mat[36],并直接传递给乘法方法。
void test()
{
double mat[36];
...
mul(mat, .., ..)
}
void mul(double* a, double* t, double*wa, int M, int N, int K)
{
// F2C array decrements.
a -= (1+M); // E.g. decrement by seven for a[6x6]!
t -= (1+N);
wa--;
...
for (j = K; j <= M; ++j) {
for (i = 1; i <= N; ++i) {
ii = K;
wa[i] = 0.;
for (p = 1; p <= N; ++p) {
wa[i] += t[p + i * t_dim1] * a[ii + j * a_dim1];
++ii;
}
}
ii = K;
for (i = 1; i <= N; ++i) {
a[ii + j * a_dim1] = wa[i];
if (j > kn) {
a[j + ii * a_dim1] = wa[i];
}
++ii;
}
}
} 所以问题是:
这是否意味着行为是未定义的,并且在执行f2c在这里所做的操作时可能会中断,即从double36数组指针中减去7,然后在正确的位置访问数组中的所有项(偏移量7)?
编辑:在C常见问题中找到了这个,这适用于这里吗?
指针算法只在指针指向同一分配内存块内的指针,或指向经过该块内存的假想“终止”元素时才定义;否则,即使指针未被取消引用,行为也是未定义的。……参考文献: K&R2,Sec.5.3第100页,证券交易委员会。5.4第102-3页,证券交易委员会。A7.7第205-6页;ISO Sec。6.3.6;理由证券分节。3.2.2.3.
更新2:
如果我使用递减索引而不是递减指针重新编译多维数组,
#define a_ref(a_1,a_2) a[(a_2)*a_dim1 + a_1 - 1 - a_dim1]
a_ref(1,2);然后,不管优化如何,该方法都会产生相同的(预期的)输出。单维数组(仅由一个数组递减)似乎不会产生任何问题。
我可以将程序中的所有多维数组更改为使用上面的访问方法,但是单个昏暗数组的数量太多,无法手动更改,因此理想情况下,我希望有一个对两者都适用的解决方案。
新问题:
发布于 2012-06-05 10:59:56
优化器只应确保没有明显的行为更改,因此它可以选择不执行递减操作,并使用递减索引访问数据(额外的偏移量可以是操作代码的一部分),因为函数使用指向数组的指针的副本。您没有告诉我们如何实际访问数组,以及优化器是否实际上引入了错误,因此我只能猜到这一点。
但是,正如slartibartfast已经说过的:这是一个未定义的行为,在检查*index >0之后,应该用int val = arr1[*index-1];代替减少
发布于 2012-06-05 10:47:53
将指针到数组移出指定的范围,然后访问它(尽管完整的表达式回到范围内)是未定义的行为AFAIK。然而,在几乎每一个实现上,这段代码都应该按照预期工作,所以问题是,您在看什么?也许在从arr1[]获取int的汇编程序指令中有一个隐含的预减量?仅仅因为您没有看到调试器中的减少,并不意味着它不存在。检查是否通过向其写入一个可区分的值来访问正确的元素。
https://stackoverflow.com/questions/10895769
复制相似问题