将ffmpeg库集成到我们项目代码中在板子上跑时候报错:Illegal instruction,通过定位是在代码中Init位置崩溃,写了个demo来验证具体崩在哪部分代码,以下代码的Init调用的是ffmpeg中的swr_init 接口,所以确定是ffmpeg编译问题。
// main.cpp : 定义控制台应用程序的入口点。
//
#include <stdio.h>
#include <stdlib.h>
#include "Swscale/IAVXSwscale.h"
int main(int argc, char * argv[])
{
int32_t avx_success = 0;
static const int32_t kAudioChannels = 1;
static const int32_t kAudioSampleRate = 16000;
IAVXSwscale * kImplSwscale = CreateSwscale(AVXSWSCALE_ID_FLTP2S16);
if (kImplSwscale == NULL)
{
printf("OpenALAudioDecoder|Init: CreateSwscale is failure\n");
return -1;
}
AVXSwscaleInfo avx_swscale_info;
avx_swscale_info.src_codec_fmt = AVXCODEC_FMT_FLT;
avx_swscale_info.src_dimension.nb_channel = kAudioChannels;//2;//lpSliceInfo->codec.channels;
avx_swscale_info.src_dimension.nb_samples = 1024 * 1;
avx_swscale_info.src_dimension.sample_rate = kAudioSampleRate;//44100;//lpSliceInfo->codec.sample_rate;
avx_swscale_info.src_dimension.channel_layout = 4;//lpSliceInfo->codec.channel_layout;
avx_swscale_info.des_codec_fmt = AVXCODEC_FMT_S16;
avx_swscale_info.des_dimension.nb_channel = kAudioChannels;
avx_swscale_info.des_dimension.sample_rate = kAudioSampleRate;
avx_swscale_info.des_dimension.nb_samples = avx_swscale_info.src_dimension.nb_samples * (avx_swscale_info.des_dimension.sample_rate * 1.0 / avx_swscale_info.src_dimension.sample_rate);
avx_swscale_info.des_dimension.nb_samples = ((avx_swscale_info.des_dimension.nb_samples + 31) / 32) * 32;
avx_swscale_info.des_dimension.channel_layout = 4;
avx_swscale_info.opt_flip = 0;
printf("OpenALAudioDecoder|Init: before\n");
avx_success = kImplSwscale->Init(avx_swscale_info);
printf("OpenALAudioDecoder|Init: after\n");
}
报错:
查询资料发现程序崩溃原因:很多编译器都在O2或者O3中开了自动向量化,这就导致很多在新体系结构中编译的可执行程序,在老机器上运行时会有Illegal instruction问题。
解决方法:在编译ffmpeg时,执行完./configure生成config.mak,修改config.mak的以下部分,删除-O3,再执行make和make install命令。
CFLAGS= -fPIC -I/home/Archive/ffmpeg-2.5.3/x264/include -I/home//Archive/ffmpeg-2.5.3/faac/include -std=c99 -fomit-frame-pointer -fPIC -mips32r2 -mdsp -mdspr2 -mhard-float -pthread -Wdeclaration-after-statement -Wall -Wdisabled-optimization -Wpointer-arith -Wredundant-decls -Wwrite-strings -Wtype-limits -Wundef -Wmissing-prototypes -Wno-pointer-to-int-cast -Wstrict-prototypes -Wempty-body -Wno-parentheses -Wno-switch -Wno-format-zero-length -Wno-pointer-sign -O3 -fno-math-errno -fno-signed-zeros -fno-tree-vectorize -Werror=format-security -Werror=implicit-function-declaration -Werror=missing-prototypes -Werror=return-type -Werror=vla -Wformat -Wno-maybe-uninitialized
扩展:
造成SIGILL的原因
1 将不正确的数据写入代码段
进程在代码段中的数据是要被作为一个指令执行的。 若不小心覆盖了已有的代码段,可能会得到错误格式的指令。 这种错误尤其在Just-In-Time即时编译器中最可能出现。
同样,如果不小心覆盖了栈上活跃记录中的返回地址,程序就可能根据这个错误地址,执行没有意义的内存中的数据,进而操作。
进一步可以认为,任何导致数据错误的问题都可能带来illegal instruction问题。比如硬盘发生故障。
2 指令集的演进
比如SIMD指令,自从奔腾4开始有MMX,X86的芯片就开始不停的增加和拓宽SIMD支持,SSE、SSE2、SSE3、SSE42、AVX、AVX2。 默认情况下,很多编译器都在O2或者O3中开了自动向量化,这就导致很多在新体系结构中编译的可执行程序,在老机器上运行时会有illegal instruction问题。
3 工具链bug
对于普通C语言通过编译器生成的可执行程序。一般都已经通过严格的测试,不会随便发生这种问题。 所以如果你遇到这种错,并且试过了静态链,而且程序中没有嵌入式汇编,基本可以断定是工具链出了问题。 编译器?汇编器或者链接器。
4 访存对齐或浮点数格式问题
根据经验,请注意出现错误的指令可能和访存地址指令有关。 另外,浮点数的格式是否符合IEEE的标准也可能会有影响。