Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clang produces illegal instruction where GCC doesn't

Tags:

c++

clang

I found a situation in which Clang produces an illegal instruction, where gcc doesn't, while experimenting with this question.

My question is: Am I doing something very wrong, or is this an actual issue with Clang?

I boiled it down to the minimal snippet necessary to reproduce the problem.

Take the file 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";
}

And the file eigen_matrix_addons.hpp:

friend std::ostream &operator<<(std::ostream &o, const Derived &m) {
    o << static_cast<const MatrixBase<Derived> &>(m);
}

(See here for a detailed explanation on what this file does. In short, its contents are placed directly into the class definition of template<class Derived> class MatrixBase;. So, this introduces another ostream operator on Derived that calls the Eigen implementation of the ostream operator on MatrixBase<Derived>. The motivation for this becomes apparent if you read this question.)

Compile with GCC and run:

$ 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.

And then compile with Clang and run:

$ 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

As you can see, the program is interrupted after executing an illegal instruction. A back-trace in gdb reveals that the issue happens in line two of 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

I.e. probably the static_cast?

My Eigen version is 3.2.0-2.1.4 according to zypper.

Edit

The dis-assembly that @Mysticial asked for:

(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.
like image 467
Lemming Avatar asked Aug 05 '14 20:08

Lemming


People also ask

Is Clang compatible with GCC?

GCC and C99 allow an array's size to be determined at run time. This extension is not permitted in standard C++. However, Clang supports such variable length arrays for compatibility with GNU C and C99 programs. If you would prefer not to use this extension, you can disable it with -Werror=vla.

What causes illegal instruction?

Illegal Instruction errors occur when you try to run a program that was compiled with some processor-specific optimizations, and is then running on a processor that fails to meet those requirements.


1 Answers

The "Illegal instruction" error is likely because your "operator <<" is missing a return statement. This leads to undefined behaviour.

Section 6.6.3 of the Standard says:

Flowing off the end of a function is equivalent to a return with no value; this results in undefined behavior in a value-returning function.

You should add:

return o;

at the end of the function.

like image 91
Henrik Avatar answered Oct 14 '22 13:10

Henrik