Illegal instruction与march编译选项

前几天在运行一个模型训练工具的时候,发现了一个Illegal instruction (core dumped)的错误。话说这种错误以前没怎么见过。这是一个开源的项目,我是运行的从同事那边拿来的工具,就会这样,但是我自己下载源码重新编译后运行一切正常。于是就查了查这个Illegal instruction是怎么回事,毕竟这货不比segmentfault常见。

查阅显示,illegal instruction,即SIGILL, 是POSIX标准中提供的一类错误。 从名字上看,SIGILL是启动的某个进程中的某一句不能被CPU识别成正确的指令。 此类错误是由操作系统发送给进程的,在进程试图执行一些形式错误、未知或者特权指令时操作系统会使用SIGILL信号终止程序。果然如名字一样,非法指令。那么,在什么情况下会出现这种错误呢,一般来说,有两种可能,一是将数据错误地写进了代码段,导致将本不是指令的数据当成指令去执行;第二种可能是编译时指定的CPU架构与实际运行的机器不一致。这里主要讲讲第二种。

由于CPU架构的演进,CPU指令集一直在不断地拓展,SSE、SSE2、SSE3、SSE42、AVX、AVX2等。不同的CPU能支持的指令集是不一样的,如果编译程序时指定了使用新的CPU架构进行编译,则该程序在老的CPU上运行时,其指令就不能被执行,从而引发Illegal instruction错误。查阅gcc资料,gcc是提供了一个march编译选项来指定所使用的CPU架构的。如果不清楚自己的CPU类型,可以使用gcc -c -Q -march=native --help=target | grep march来查看:

music@ds01:~$ gcc -c -Q -march=native --help=target | grep march
  -march=                             corei7-avx
music@ds01:~$

如果在编译时指定了-march参数,gcc将不会再用兼容的指令去编译,而是根据指定的CPU架构,采用其特定的指令集如AVX去生成二进制代码。因此,当你确定所编译的程序只会在特定的环境中运行时,可以使用-march参数来指定CPU架构,这样编译器就可以根据你的CPU架构进行指令上的优化,而这个指定带来的结果就是,如果你将程序放在其他机器上运行,有可能得到Illegal instruction的运行错误。

 

posted @ 2017-05-08 09:12  重复啦  阅读(5310)  评论(0编辑  收藏  举报