2016-05-23 193 views
1

当我执行以下代码:分段故障

AVFrame tmp = frames_video1[k]; //AVFrame frames_video1[] 
AVFrame *avf1 = &tmp; 
AVFrameSideData* avfsd1=NULL; 
if(avf1->side_data != NULL) 
    printf("avf1->side_data is not NULL!!...........\n"); 
avfsd1 = av_frame_get_side_data(avf1, AV_FRAME_DATA_MOTION_VECTORS); 

我遇到分段错误来得av_frame_get_side_data(avf1,AV_FRAME_DATA_MOTION_VECTORS)发生了:

avf1->side_data is not NULL!!........... 
Segmentation fault (core dumped) 

为什么呢?

+0

如果我们提供了[最小,完整,可验证示例](http://stackoverflow.com/help/mcve),这将非常有帮助。然而,看起来frames_video1 [k]可能导致NULL或其他无效值,并且在分配'avf1 =&tmp'之前,您没有检查'tmp == NULL'或做任何其他类型的理智检查。即使它不为null,如果你正在访问超过'frames_video'的边界,你可能会得到垃圾数据而不是空值。 –

+0

frames_video1 [k]不为空,否则就不会有输出“avf1-> side_data不是NULL !! ............” – user273653

+0

或者是tmp。如何在分配avf1 =&tmp时执行完整性检查? – user273653

回答

1

这里是GDB的输出:

(gdb) print avf1->side_data->type 
Cannot access memory at address 0x0 

(gdb) print frames_video1[1]->side_data->type 
Cannot access memory at address 0x0 

出奇,avf1指向一个已损坏的帧,其side_data->type为空,这是不正常的。问题的原因在于其他地方。

0
AVFrame tmp = frames_video1[k]; //AVFrame frames_video1[] 
AVFrame *avf1 = &tmp; 

你不能做到这一点。我不知道你在哪里学到了这些,但这是不允许的,从根本上不能工作。你不知道应用程序中AVFrame的大小(它不是FFmpeg的ABI的一部分),所以你不能在栈上放置一个副本。相反,这样做:

AVFrame *avf1 = frames_video1[k]; 

永远不要复制堆栈上的FFmpeg对象,它将无法工作。这也意味着frames_video1 []需要是AVFrame *的数组,即AVFrame指针,而不是数组AVFrame。如果你不明白为什么,请阅读C语言中的指针和内存,并再次记住AVFrame的大小不是FFmpeg ABI的一部分。

现在,我们来调试你的对象。首先,C栈的基础知识:frames_video1[]中有多少个帧,k是什么?什么是frames_video1[k]->data[0]frames_video[k]->linesize[0]?他们合法吗?你确定frames_video1[k]是合法对象吗?事实上,一些不存在的内存副本是非NULL意味着什么。

其次,如果对象是合法的,什么是AVFrame->nb_side_data?您不能在该索引之外访问AVFrame->side_data[]

(gdb) print avf1->side_data->type 

你不能做,要么。 side_data[]是一个指针数组,所以不是这样做:

(gdb) print avf1->side_data[0]->type 

所有这一切说,我再次强烈建议您在C指针和内存分配读了,我不认为你完全理解它。 FFmpeg是一个非常低级的C库,不了解C会导致很多悲伤。