在Clang 3.9上使用-O2
编译以下示例会导致reproFunction在1.9038e+185
中调用时返回垃圾(main
):
double reproFunction(const Eigen::Matrix3d& R_in)
{
const Eigen::Matrix3d R = R_in;
Eigen::Matrix3d Q = R.cwiseAbs();
if(R(1,2) < 2) {
Eigen::Vector3d n{0, 1, R(1, 2)};
double s2 = R(1,2);
s2 /= n.norm();
}
return R(1, 2);
}
int main() {
Eigen::Matrix3d R;
R = Eigen::Matrix3d::Zero(3,3);
// This fails - reproFunction(R) returns 0
R(1, 2) = 0.7;
double R12 = reproFunction(R);
bool are_they_equal = (R12 == R(1,2));
std::cout << "R12 == R(1,2): " << are_they_equal << std::endl;
std::cout << "R12: " << R12 << std::endl;
std::cout << "R(1, 2): " << R(1, 2) << std::endl;
}
R12 == R(1,2): 0
R12: 1.9036e+185
R(1, 2): 0.7
reproFunction
,通过R
的分配初始化R_in
(,即const )。它返回R(1, 2)
。在分配和返回之间,reproFunction
在多个操作中使用R
,但它们都不能更改R
。删除任何这些操作会导致reproFunction
返回正确的值。
在以下任何情况下都不会出现此行为:
-O1
或更低现在问题:这种行为是由于我在上面的代码中遗漏的错误,Eigen 3.3.3中的错误,还是Clang 3.9中的错误?
可在https://github.com/avalenzu/eigen-clang-weirdness找到一个独立的复制示例。
答案 0 :(得分:4)
我可以用clang 3.9重现这个,但不能用clang 3.8重现。我将Eigen的问题一分为this commit from 2016-05-24 21:54:
错误256:使用未对齐的加载/存储启用矢量化。这涉及所有架构和所有规模。可以通过定义EIGEN_UNALIGNED_VECTORIZE = 0
来禁用此新行为
该提交启用了对未对齐数据的矢量化操作。
我仍然认为,这是clang中的一个错误,但您可以通过编译来解决它
-D EIGEN_UNALIGNED_VECTORIZE=0
此外,如果将clang 3.9检测为编译器,则可以通过自动禁用此功能来“固定”Eigen。