【发布时间】:2019-05-15 15:02:09
【问题描述】:
以下代码在 clang++ 中工作,但在 g++ 中崩溃了
#include<vector>
#include<iostream>
template<class Iterator>
double abs_sum(double current_sum, Iterator it, Iterator it_end){
if (it == it_end)
return current_sum;
return abs_sum(current_sum+std::abs(*it),++it,it_end);
}
int main(int argc, char** argv){
std::vector<double> values {1.0, 2.0,-5};
std::cout << abs_sum(0.0,values.begin(),values.end()) << std::endl;;
}
罪魁祸首原来是这行:
return abs_sum(current_sum+std::abs(*it),++it,it_end);
在 clang 中,*it 在 ++it 之前评估,在 g++ 中则相反,导致迭代器在被取消引用之前增加。事实证明,评估函数参数的顺序是实现定义的。
我的问题是:我如何捕捉这种类型的错误?理想情况下,当我不小心依赖于实现的具体细节时,我希望有一个错误或至少一个警告。
clang 和 gcc 都不会产生任何警告,即使使用 -Wall。
【问题讨论】:
-
在调用函数之前按正确的顺序执行操作。
-
请定义“壮观的崩溃” :D 它包括声音和灯光吗?
-
添加另一个单元测试。
-
@Bernhard 单元测试在这里不一定对你有帮助。如果你有 UB,那么任何事情都可能发生,你不能依靠测试来捕捉它。这是最难发现的错误类别,最终它实际上只是代码审查和纯属偶然。我确实同意这样的测试应该存在,因为如果你经常运行你的单元测试,那么你会增加这个错误弹出并因此被发现的机会;但是,该错误很可能仅在更复杂的程序中出现症状。
-
这些很难捕捉,我们可以找到各种难以捕捉的有趣案例,例如this one和this one。这是changing the evaluation order rules in C++17 的动机,但我们没有确定这个具体的。
标签: c++ undefined-behavior unspecified-behavior