- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
在调查问题时,我偶然发现了代码,它归结为以下示例:
const unsigned long long int MAX=9223372036854775807ULL; //2^63-1
void double_it(double *d){
for(unsigned long long int i=0;i<MAX; i++){
d[i]=2*d[i];
}
}
由于一些错误,for 循环运行的距离远远超过内存,程序崩溃了。但这不是有趣的部分。
当使用 gcc (gcc -O2 -Wall -std=c99 -c
) 编译时,此代码会导致以下警告:
warning: iteration 2305843009213693951ull invokes undefined behavior [-Waggressive-loop-optimizations]
这是我不明白的原因。
stackoverflow上有一些类似的问题,例如:
但那些问题是整数溢出,这里的计数器 i
似乎远未溢出。
在没有-O2
的情况下编译相同的代码不会导致这样的警告,所以我猜-Waggressive-loop-optimizations
是一个重要的部分。
其实我有两个问题:
-O2
就没有警告?如果这段代码有问题,无论是否优化,我都认为它是有问题的。g++ 的行为是相同的(在线查看 coliru)。
最佳答案
But those problems were integer overflows, here the counter i is seemingly nowhere near an overflow.
为什么会这样想?
d[i]
与 *(d + i)
相同。 d + i
明显溢出,因为 double 的大小超过 2(不确定标准中是否有任何说明,但可以很安全地假设您的架构就是这样)。准确地说,sizeof 与此并不完全相关,但这是代码在编译器内部转换成的内容。
在 C11 §6.5.6 中我们可以读到:
If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined
我们可以颠倒那句话的逻辑。如果加法明显溢出,那么一定是未定义的行为。
您没有收到警告的原因是编译器没有义务就所有未定义的行为向您发出警告。这是编译器的礼貌。通过优化,编译器会花更多时间推理代码的作用,因此它有机会发现更多不良行为。如果不进行优化,它不会浪费时间这样做。
关于c - "iteration ... invokes undefined behavior [-Waggressive-loop-optimizations]"警告的不明显原因,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42859795/
通常当我请求线程转储时,系统性能不佳的症状很容易解释;也就是说,通常我会看到许多线程显然正在等待一个已被获取但未被另一个释放的监视器。 在这种情况下,我有很多线程在等待监视器 (0x965ad100)
C:\Users\shagy\Desktop\3RD YEAR 2ND SEMESTER\SPM\Newfolder\SPM-SMS>npm start npm ERR! path C:\Users\
我是一名优秀的程序员,十分优秀!