Consider the following code (uses Eigen ):
#include <Eigen/Dense> #include <iostream> template<int rows, int cols, int row, class R, class Rv, int N, class... Rs> inline typename std::enable_if<sizeof...(Rs)==0>::type setRow(Eigen::Matrix<R,rows,cols>&) {} template<int rows, int cols, int row, class R, class Rv, int N=0, class... Rs> inline typename std::enable_if<sizeof...(Rs)==cols-N-1>::type setRow(Eigen::Matrix<R,rows,cols>& m, Rv val, Rs...args) { m(row,N)=val; setRow<rows,cols,row,R,Rv,N+1>(m,args...); } template<class T, int R, int C, int CUR_ROW> class MatrixConstructor { Eigen::Matrix<T,R,C> m; public: MatrixConstructor(const Eigen::Matrix<T,R,C>& m) : m(m) {} MatrixConstructor() {} template<class...Ts> typename std::enable_if<sizeof...(Ts)==C && CUR_ROW<R-1, MatrixConstructor<T,R,C,CUR_ROW+1>>::type operator()(Ts... vals) { setRow<R,C,CUR_ROW>(m,vals...); return MatrixConstructor<T,R,C,CUR_ROW+1>(m); } template<class...Ts> typename std::enable_if<sizeof...(Ts)==C && CUR_ROW==R-1, Eigen::Matrix<T,R,C>>::type operator()(Ts... vals) { setRow<R,C,CUR_ROW>(m,vals...); return m; } }; void test() { Eigen::Matrix<double,4,3> m=MatrixConstructor<double,4,3,0>()(1,2,3) (4,5,6) (7,8,9) (5,4,3); std::cout << m; } int main() { test(); }
I will compile it with gcc-4.8 with full optimization and the ability to generate a list of assemblies. Here is the command I'm using:
g++ minitest.cpp -I/usr/include/eigen3 -std=c++0x -O3 -march=native -S -masm=intel
(My processor is Intel (R) Xeon (R) CPU E3-1226 v3, running on a 64-bit Linux system - I hope now -march=native makes sense to readers.)
Interestingly, some of the instructions created using this command line seem pointless and even redundant. See how the test() function starts after the stack is configured (for the full code for test() and main() see here ):
vmovsd xmm4, QWORD PTR .LC6[rip] # 1.0 lea rsi, [rsp+96] vmovsd xmm5, QWORD PTR .LC7[rip] # 2.0 vmovsd QWORD PTR [rsp], xmm4 vmovapd xmm3, XMMWORD PTR [rsp+16] # What does it read?! vmovapd xmm1, XMMWORD PTR [rsp] # And this! vmovsd QWORD PTR [rsp+32], xmm5 vmovsd xmm0, QWORD PTR .LC8[rip] # 3.0 vmovapd XMMWORD PTR [rsp+304], xmm3 # And now even save this junk?! vmovapd XMMWORD PTR [rsp+192], xmm1 vmovapd xmm3, XMMWORD PTR [rsp+48] vmovapd xmm1, XMMWORD PTR [rsp+32] vmovsd QWORD PTR [rsp+64], xmm0 vmovsd xmm7, QWORD PTR .LC12[rip] # 7.0 vmovapd XMMWORD PTR [rsp+336], xmm3 vmovapd XMMWORD PTR [rsp+224], xmm1 vmovapd xmm3, XMMWORD PTR [rsp+80] vmovsd QWORD PTR [rsp+304], xmm7 # Even stranger β overwrites the junk
I went through these spam readings in the debugger and confirmed that after them the xmm3 and xmm1 registers really have meaningless values. Looking at this reading of undefined values, I begin to suspect that my program is really trying to access some memory that should be inaccessible. But why? Did I introduce somewhere UB?
I also tried to run a program compiled with -fsanitize=address , but it worked without crashing.