为什么在使用 Clang 3.9 时返回复制的 Matrix3d 的元素会导致输出不正确?
Why does returning an element of a copied Matrix3d result in incorrect output when using Clang 3.9?
在 Clang 3.9 上使用 -O2
编译以下示例会导致在 main
中调用 returning 垃圾 (1.9038e+185
):
代码
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_in
的赋值初始化 R
( 是 const)。它 returns R(1, 2)
。在赋值和return之间,reproFunction
在几个操作中使用了R
,但是其中none应该可以改变R
。删除任何这些操作都会导致 reproFunction
return 得到正确的值。
以下任何一种情况都不会出现此行为:
- 程序使用 Clang 3.5、Clang 4.0 或 g++-5.4 编译。
- 优化级别为
-O1
或更低
- 使用 Eigen 3.2.10 而不是 Eigen 3.3.3
现在的问题是:这种行为是由于我在上面的代码中遗漏的错误、Eigen 3.3.3 中的错误还是 Clang 3.9 中的错误造成的?
找到独立的复制示例
我可以用 clang 3.9 重现这个,但不能用 clang 3.8。我将 Eigen 方面的问题一分为二 this commit from 2016-05-24 21:54:
Bug 256: enable vectorization with unaligned loads/stores. This concerns all architectures and all sizes. This new behavior can be disabled by defining EIGEN_UNALIGNED_VECTORIZE=0
该提交启用了对未对齐数据的矢量化操作。
我仍然认为,这是 clang 中的一个错误,但您可以通过使用
进行编译来解决它
-D EIGEN_UNALIGNED_VECTORIZE=0
此外,如果检测到 clang 3.9 作为编译器,Eigen 可以 'fixed' 通过自动禁用此功能。
在 Clang 3.9 上使用 -O2
编译以下示例会导致在 main
中调用 returning 垃圾 (1.9038e+185
):
代码
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_in
的赋值初始化 R
( 是 const)。它 returns R(1, 2)
。在赋值和return之间,reproFunction
在几个操作中使用了R
,但是其中none应该可以改变R
。删除任何这些操作都会导致 reproFunction
return 得到正确的值。
以下任何一种情况都不会出现此行为:
- 程序使用 Clang 3.5、Clang 4.0 或 g++-5.4 编译。
- 优化级别为
-O1
或更低 - 使用 Eigen 3.2.10 而不是 Eigen 3.3.3
现在的问题是:这种行为是由于我在上面的代码中遗漏的错误、Eigen 3.3.3 中的错误还是 Clang 3.9 中的错误造成的?
找到独立的复制示例我可以用 clang 3.9 重现这个,但不能用 clang 3.8。我将 Eigen 方面的问题一分为二 this commit from 2016-05-24 21:54:
Bug 256: enable vectorization with unaligned loads/stores. This concerns all architectures and all sizes. This new behavior can be disabled by defining EIGEN_UNALIGNED_VECTORIZE=0
该提交启用了对未对齐数据的矢量化操作。
我仍然认为,这是 clang 中的一个错误,但您可以通过使用
进行编译来解决它-D EIGEN_UNALIGNED_VECTORIZE=0
此外,如果检测到 clang 3.9 作为编译器,Eigen 可以 'fixed' 通过自动禁用此功能。