我在 SO 上读到一个关于导致运行时错误(即段错误)的代码的问题。
我尝试使用 ideone.com 调试代码,但得到了一个奇怪的结果。
我已将代码精简为最小版本以重现奇怪的行为。因此代码没有做任何有意义的事情。代码的目的只是为了展示奇怪的行为。
代码示例 1:
#include <stdio.h>
int main() {
int a[3] = {3, 2, 5};
int s[3] = {0, 0, 0};
int r = 0;
int i;
for(i = 1; i < 3; i++) {
while((a[i] < a[s[r]]) && (r >= 0))
{
r--;
}
printf("initialize s[%d] to %d\n", r+1, i);
++r;
s[r] = i;
}
printf("%d\n", r);
return 0;
}
此代码给出运行时错误。
参见 https://ideone.com/IWo6TS#stdin
所以我对代码做了这个小改动。
代码示例 2:
#include <stdio.h>
int main() {
int a[3] = {3, 2, 5};
int s[3] = {0, 0, 0};
int r = 0;
int i;
for(i = 1; i < 3; i++) {
int t = s[r]; // These 2 lines
while((a[i] < a[t]) && (r >= 0)) //
// while((a[i] < a[s[r]]) && (r >= 0)) // instead of this line
{
r--;
}
printf("initialize s[%d] to %d\n", r+1, i);
++r;
s[r] = i;
}
printf("%d\n", r);
return 0;
}
现在代码运行良好并产生输出:
initialize s[0] to 1
initialize s[1] to 2
1
参见 https://ideone.com/qt43DL#stdin
使用的编译器是GCC 6.3。
区别仅在于:
.... a[s[r]] .... in example 1
和
int t = s[r]; in example 2
.... a[t] ....
那么问题是为什么第一个示例失败而第二个示例执行正常?
我在代码中寻找 UB,但找不到任何东西。代码中有UB吗?
这是 GCC 6.3 中的(已知)错误吗?
更新
正如 Scott Hunter 正确指出的那样,两个代码示例不做同样的事情。
第一个示例由于 UB 而失败,因为变量 r
在 while
的主体内更改为 -1,并且在 while 的下一个条件检查中
它访问 s[-1]
。所以 UB 例如 1。
最佳答案
在这两个版本中,r
在while
循环中改变;因此,在第一个版本中与 a[i]
进行比较的 a
元素的索引发生了变化,但在第二个版本中没有变化。
关于c - 使用另一个数组索引一个数组 - gcc 6.3 运行时错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46103000/