GC和onTouch在使用ffmpeg到ndk的应用程序中导致致命信号11(SIGSEGV)错误

grz*_*byk 4 android ffmpeg segmentation-fault android-ndk ontouchlistener

在使用FFmpeg和NDK时,我遇到了一个令人讨厌但众所周知的错误:

A/libc(9845): Fatal signal 11 (SIGSEGV), code 1, fault addr 0xa0a9f000 in tid 9921 (AsyncTask #4)
Run Code Online (Sandbox Code Playgroud)

UPDATE

几个小时后,我发现可能有两个问题来源.一个与多线程有关.我查了一下,然后修好了.现在,只有在视频播放(ndk)打开时,应用程序才会崩溃.

我在触摸事件中放了一个"计数器"

  surfaceSterowanieKamera.setOnTouchListener(new View.OnTouchListener() {
            int counter = 0;
            @Override
            public boolean onTouch(View v, MotionEvent event) {             
                if ((event.getAction() == MotionEvent.ACTION_MOVE)){
                    Log.i(TAG, "counter = " + counter);
                    //cameraMover.setPanTilt(some parameters);
                    counter++;
                 }
Run Code Online (Sandbox Code Playgroud)

我开始逐个禁用其他应用功能,但没有视频.我发现,每减少一个功能,压缩需要更长的时间 - 计数器达到更高的值.在关闭视频播放和触摸界面(cameraMover.setPanTilt()注释掉)之外的所有内容后,应用程序通常在计数器介于1600 - 1700之间时会崩溃.

在这种情况下,logcat显示上述错误和GC相关信息.对我而言,似乎GC正在搞乱ndk.

01-23 12:27:13.163: I/Display Activity(20633): n = 1649
01-23 12:27:13.178: I/art(20633): Background sticky concurrent mark sweep GC freed 158376(6MB) AllocSpace objects, 1(3MB) LOS objects, 17% free, 36MB/44MB, paused 689us total 140.284ms
01-23 12:27:13.169: A/libc(20633): Fatal signal 11 (SIGSEGV), code 1, fault addr 0x9bd6ec0c in tid 20734 (AsyncTask #3)
Run Code Online (Sandbox Code Playgroud)

为什么GC导致ndk部分应用程序出现问题?


原始问题

我在做什么?

我正在开发一个应用程序,从网络摄像头流式传输实时视频,并使用户能够平移和倾斜远程摄像头.我正在使用用NDK构建的FFmpeg库来实现流畅的播放,几乎没有延迟.

我正在使用FFMpeg库连接到视频流.然后ndk部分创建位图,对SurfaceView videoSurfaceView位于android活动(java部分)中的对象进行图像处理和渲染帧.

为了移动网络摄像头,我创建了一个单独的类 - public class CameraMover implements Runnable{/**/}.此类是一个单独的线程,通过套接字与远程摄像头连接,并管理仅通过云台移动连接的任务.

接下来在主要活动中我创建了一个触摸监听器

videoSurfaceView.setOnTouchListener(new View.OnTouchListener() {/**/
cameraMover.setPanTilt(some parameters);
/**/}
Run Code Online (Sandbox Code Playgroud)

它读取用户的手指移动并向摄像机发送命令.

所有任务 - 移动相机,触摸界面和视频播放都可以正常工作,当其他人被禁用时,即当我禁用移动相机的可能性时,我可以观看视频流和注册触摸事件直到时间结束(或电池)至少).仅当任务配置为同时工作时才会出现此问题.

我无法找到重现问题的步骤.它只是发生,但只有在用户触摸屏幕移动相机后.它可以在第一次交互后15秒,但有时需要10分钟或更长时间才能崩溃.通常它是一分钟左右的东西.

我做了什么来解决它?

  • 我试图在logcat中显示数百万个日志以查找错误,但最后一个日志总是不同的.
  • 我创建了一个透明的表面,我把它放在videoSurfaceView并分配了触摸监听器.这一切都以同样的错误结束.
  • 正如我之前提到的,我关闭了一些功能以找出哪一个产生错误,但似乎只有当一切都同时工作时才会发生错误.

错误的类型

几乎每次错误看起来像这样:

A/libc(11528): Fatal signal 11 (SIGSEGV), code 1, fault addr 0x9aa9f00c in tid 11637 (AsyncTask #4)
Run Code Online (Sandbox Code Playgroud)

两个错误之间的差异是libc,addr number和tid number之后的数字.很少AsyncTask数量变化 - 我收到了#1几次,但我无法重现它.

我怎样才能避免这个错误?它的来源是什么?

mst*_*sjo 8

您引用的错误消息libc: Fatal signal 11 (SIGSEGV)并没有说明实际发生的事情 - 这只是说某些东西试图错误地访问内存(读取或写入).由于这是一个C api,它可能只是任何错误 - 使用指针,使用不再有效的指针,将太多数据写入太小的缓冲区等.

所以遗憾的是,这并没有提供太多线索 - 如果没有看到相关的C代码,就不可能说出导致这种情况的原因.

通常,设备日志还包含某种调试信息,这些信息至少可以提供错误发生位置的模糊提示 - 请参阅最简单的方法来调试本机库中的崩溃,由Android应用程序链接?举个例子.这篇文章还包含有关启用CheckJNI以获得有关滥用JNI函数的更好调试信息的提示,这可能是导致问题的原因之一.NDK的还包含了工具ndk-stackndk-gdb可用于获取有关崩溃的发生位置更精确的信息.

请注意,即使您获得了崩溃发生位置的精确定位,也可能无法直接指向代码中的错误位置.

在这种情况下,当你说它似乎是GC导致它时,听起来像是你通过JNI滥用java对象 - 好像你保持对java对象的引用而不通过JNI正确保存引用.当GC运行时,它可以移动分配的数据,假设没有人保持直接指向它.

请参阅http://android-developers.blogspot.com/2011/07/debugging-android-jni-with-checkjni.html以获取有关它可能的更多提示.