c++ - 为什么即使启用了优化功能,std::vector::at()也需要进行边界检查?

原文 标签 c++ windows optimization dll indexoutofboundsexception

我在Windows中的libstdc++-6.dll有问题。这段代码:

#include <iostream>
#include <vector>
int main(){
    std::vector<int> x(10);
    std::cout << x.at(3) << std::endl;
}

编译正常,但是当我运行它时,我收到一条错误消息,说

在DLL libstdc ++-6.dll中找不到过程入口点_ZSt24__throw_out_of_range_fmtPKcz

我的问题是而不是如何解决此问题(很可能是dll版本错误,我只需要修复PATH)。但是,这使我意识到一些出乎意料的事情:

当我打开优化功能时,以上代码运行良好(无论错误的dll如何),即
g++ error.cxx -O2

但是这段代码
#include <vector>
#include <iostream>

double Foo(const std::vector<int>& x,int index) {    
    int m = x.at(index + 1) - x.at(index);
    int b = x.at(index);
    return b/(m*1.0);
}        
int main(){}

才不是。

无论我是否通过第二个代码进行编译,为什么都出现上述错误?
g++ error.cxx -O2     or       g++ error.cxx 



同样,我知道为什么会出现该错误,但是我希望打开优化后,两个版本都不会导致该错误。相反,第一个版本运行良好,而第二个版本则运行不正常。 -O2不应该完全消除边界检查吗?

最佳答案

C++标准要求对at()进行边界检查,而at()的实际实现代码确实包含边界检查。

但是,在第一种情况下,边界是硬编码的(10个元素与索引3相比),并且“一切”都用-O2内联,因此编译器的优化器会删除边界检查违规的代码,因为它可以在编译时证明确保不违反边界且未采用代码路径(按规则)。

因此,在这种情况下,您不会收到-O2的链接器错误,因为编译器根本没有发出调用指令。


-O2是否不应该完全消除边界检查?

不,优化器必须保留the AS-IF rule,即,如果优化器可以在编译时证明未采用代码路径,则可以消除该代码。它不仅会故意删除源代码中引入的检查。

附带说明一下,对于不需要边界检查的vector::operator[],一种实现可以(例如合理地)引入调试边界检查。未定义NDEBUG,仅在定义NDEBUG时不进行检查。但是,在这种情况下,如果需要的话,边界检查将“由预处理器除去”,而不是由优化器除去。

相关文章:

c++ - C++中输出顺序错误

c++ - 如何计算 double 数组中特定范围内的值数

java - 通过命令提示符将Java程序安装为Windows服务

c# - 如何确定我的桌面程序是否正在控制台上运行?

c++ - 如何管理指向已引用对象内部数据的shared_ptr?

flash - 如何优化模块化Flash应用程序(加载时间和灵活性)?

c++ - C++-如何删除打印到控制台的换行符

c++ - 我可以从这个矩阵算法得到旋转

c++ - 有什么简单的方法可以确定何时关闭弹出菜单?

javascript - 查找网格中所需位置周围的空单元的算法