我在这个问题进行实验时,发现了一种情况:Clang会生成一个非法指令,而gcc不会。
我的问题是:我是否做错了什么,还是这是Clang的一个实际问题?
我将其简化为最小的代码片段以重现问题。请取文件eigen.cpp
:
#include <iostream>
#define EIGEN_MATRIXBASE_PLUGIN "eigen_matrix_addons.hpp"
#include <Eigen/Dense>
int main() {
Eigen::Matrix2d A;
A << 0, 1, 2, 3;
std::cout << A << "\n";
}
还有文件eigen_matrix_addons.hpp
:
friend std::ostream &operator<<(std::ostream &o, const Derived &m) {
o << static_cast<const MatrixBase<Derived> &>(m);
}
(详见此处,其中有关于此文件的详细解释。简而言之,它的内容直接放置在template<class Derived> class MatrixBase;
类定义中。因此,它为Derived
引入了另一个ostream运算符,该运算符调用MatrixBase<Derived>
的Eigen实现的ostream运算符。阅读此问题后,这一动机变得显然。)
使用GCC编译并运行:
$ g++ -std=c++11 -Wall -Wextra -pedantic -isystem/usr/include/eigen3 -I. -o eigen_gcc eigen.cpp
$ ./eigen_gcc
0 1
2 3
$ g++ --version
g++ (SUSE Linux) 4.8.1 20130909 [gcc-4_8-branch revision 202388]
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
然后使用Clang进行编译并运行:
$ clang++ -std=c++11 -Wall -Wextra -pedantic -isystem/usr/include/eigen3 -I. -o eigen_clang eigen.cpp
$ ./eigen_clang
0 1
Illegal instruction
$ clang++ --version
clang version 3.4 (branches/release_34 198681)
Target: x86_64-suse-linux
Thread model: posix
你可以看到,在执行非法指令后,程序被中断了。在gdb中进行回溯可以发现问题出现在eigen_matrix_addons.hpp
的第二行:
(gdb) bt
#0 0x00000000004013e1 in Eigen::operator<< (o=..., m=...)
at ./eigen_matrix_addons.hpp:2
#1 0x00000000004010f0 in main () at eigen.cpp:15
也就是说可能是static_cast
?
根据zypper
,我的Eigen版本为3.2.0-2.1.4。
编辑
@Mysticial要求的反汇编:
(gdb) disass
Dump of assembler code for function Eigen::operator<<(std::ostream&, Eigen::Matrix<double, 2, 2, 0, 2, 2> const&):
0x00000000004013c0 <+0>: push %rbp
0x00000000004013c1 <+1>: mov %rsp,%rbp
0x00000000004013c4 <+4>: sub $0x20,%rsp
0x00000000004013c8 <+8>: mov %rdi,-0x10(%rbp)
0x00000000004013cc <+12>: mov %rsi,-0x18(%rbp)
0x00000000004013d0 <+16>: mov -0x10(%rbp),%rdi
0x00000000004013d4 <+20>: mov -0x18(%rbp),%rsi
0x00000000004013d8 <+24>: callq 0x4013f0 <Eigen::operator<< <Eigen::Matrix<double, 2, 2, 0, 2, 2> >(std::ostream&, Eigen::DenseBase<Eigen::Matrix<double, 2, 2, 0, 2, 2> > const&)>
0x00000000004013dd <+29>: mov %rax,-0x20(%rbp)
=> 0x00000000004013e1 <+33>: ud2
End of assembler dump.
Intel(R) Core(TM) i5-3340M CPU @ 2.70GHz
。我已经将反汇编代码添加到问题中。 - Lemmingud2
告诉 CPU 引发无效的操作码指令。因此,Clang 故意使程序崩溃。有趣的是,在这种情况下,大多数编译器甚至不会编译,如果省略返回值。 - Mysticial