我有段代码可以计算一个数组下标,如果这个下标是合法的话,就会访问数组中对应的元素。类似于:
int b = rowCount() - 1;
if (b == -1) return;
const BlockInfo& bi = blockInfo[b];
我担心这可能会引发未定义的行为。例如,编译器可能假定b始终为非负数,因为我用它来索引数组,因此它将优化if语句。
在什么情况下,如果您对无效结果不做任何操作,"访问"数组越界是安全的?如果blockInfo
不是实际数组,而是像vector
这样的容器,是否会改变情况?如果这是不安全的,我能通过将访问放在else语句中来修复它吗?
if (b == -1) {
return;
} else {
const BlockInfo& bi = blockInfo[b];
}
最后,是否有类似于
-fno-strict-aliasing
或-fno-delete-null-pointer-checks
的编译器标志,使编译器“做正确的事情”并防止任何不必要的行为?为了澄清:我的担忧特别是由于另一个问题,即您打算在访问指针之前测试它是否为非空。编译器会将其转换并推断出,由于您正在对其进行解引用,因此它不能为null!类似于这样的东西(未经测试):
void someFunc(struct MyStruct *s) {
if (s != NULL) {
cout << s->someField << endl;
delete s;
}
}
我记得听说在C++中仅仅创建越界数组访问就是UB。 因此编译器可以合法地假定数组索引不越界,并删除相反的检查。
rowCount
返回一个int
,可以是零或正数(还有什么其他意义呢?)。 严格来说,我不是在问“编译器优化会引入错误”(虽然非常口语化地说,是的,这就是我想知道的)。严格来说,我想知道1)何时何时不使用无效索引访问数组是未定义行为
,其中“使用”表示该语句不一定被执行,并且2)编译器何时可以使用它来生成与我的意图相违背的代码。 - jdm