我在Android中使用openSmile 2.0-rc1库,我面临着一个非常烦人的问题。当我第一次运行runAnalysis
时没有任何问题。我得到了有效的结果。但是,当我使用相同的参数运行相同的函数两次我的应用程序崩溃时,我收到此错误:
07-18 11:47:22.609 5128-5128/com.test A/libc: Fatal signal 6 (SIGABRT), code -6 in tid 5128 (com.test)
07-18 11:47:22.711 196-196/? A/DEBUG: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
07-18 11:47:22.711 196-196/? A/DEBUG: Build fingerprint: 'google/hammerhead/hammerhead:6.0.1/user/release-keys'
07-18 11:47:22.711 196-196/? A/DEBUG: Revision: '11'
07-18 11:47:22.711 196-196/? A/DEBUG: ABI: 'arm'
07-18 11:47:22.711 196-196/? A/DEBUG: pid: 5128, tid: 5128, name: com.test >>> com.test <<<
07-18 11:47:22.711 196-196/? A/DEBUG: signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
07-18 11:47:22.723 196-196/? A/DEBUG: r0 00000000 r1 00001408 r2 00000006 r3 b6f7eb7c
07-18 11:47:22.723 196-196/? A/DEBUG: r4 b6f7eb84 r5 b6f7eb34 r6 0000000b r7 0000010c
07-18 11:47:22.723 196-196/? A/DEBUG: r8 9eb91e40 r9 9c97a9c0 sl aa125d80 fp 00000001
07-18 11:47:22.723 196-196/? A/DEBUG: ip 00000006 sp bedf5848 lr b6cedb61 pc b6ceff50 cpsr 400f0010
07-18 11:47:22.737 196-196/? A/DEBUG: backtrace:
07-18 11:47:22.737 196-196/? A/DEBUG: #00 pc 00041f50 /system/lib/libc.so (tgkill+12)
07-18 11:47:22.737 196-196/? A/DEBUG: #01 pc 0003fb5d /system/lib/libc.so (pthread_kill+32)
07-18 11:47:22.737 196-196/? A/DEBUG: #02 pc 0001c30f /system/lib/libc.so (raise+10)
07-18 11:47:22.737 196-196/? A/DEBUG: #03 pc 000194c1 /system/lib/libc.so (__libc_android_abort+34)
07-18 11:47:22.737 196-196/? A/DEBUG: #04 pc 000174ac /system/lib/libc.so (abort+4)
07-18 11:47:22.737 196-196/? A/DEBUG: #05 pc 000c12e7 /data/app/com.test-1/lib/arm/libopenSmile.so (_ZN9__gnu_cxx27__verbose_terminate_handlerEv+226)
07-18 11:47:22.737 196-196/? A/DEBUG: #06 pc 00091e05 /data/app/com.test-1/lib/arm/libopenSmile.so (_ZN10__cxxabiv111__terminateEPFvvE+4)
07-18 11:47:22.737 196-196/? A/DEBUG: #07 pc 00091e79 /data/app/com.test-1/lib/arm/libopenSmile.so (_ZSt9terminatev+8)
07-18 11:47:22.737 196-196/? A/DEBUG: #08 pc 00091f9d /data/app/com.test-1/lib/arm/libopenSmile.so (__cxa_throw+120)
07-18 11:47:22.737 196-196/? A/DEBUG: #09 pc 00033a73 /data/app/com.test-1/lib/arm/libopenSmile.so (_ZNK10ConfigType10findFieldHEPKcPiPPKS_S2_PPc+346)
07-18 11:47:22.737 196-196/? A/DEBUG: #10 pc 00034d5f /data/app/com.test-1/lib/arm/libopenSmile.so (_ZN17cFileConfigReader11getInstanceEPKcPK10ConfigTypeP14cConfigManager+854)
07-18 11:47:22.737 196-196/? A/DEBUG: #11 pc 00036a73 /data/app/com.test-1/lib/arm/libopenSmile.so (_ZN14cConfigManager10readConfigEv+102)
07-18 11:47:22.737 196-196/? A/DEBUG: #12 pc 00090df3 /data/app/com.test-1/lib/arm/libopenSmile.so (runAnalysis+194)
07-18 11:47:22.738 196-196/? A/DEBUG: #13 pc 00fe573f /data/app/com.test-1/oat/arm/base.odex (offset 0xb75000) (void com.test.probing.probe.voiceAnalysis.OpenSmile.runAnalysis(java.lang.String, java.lang.String, java.lang.String, java.lang.String)+170)
07-18 11:47:22.738 196-196/? A/DEBUG: #14 pc 00fe532d /data/app/com.test-1/oat/arm/base.odex (offset 0xb75000) (java.lang.String com.test.probing.probe.voiceAnalysis.OpenSmile.runAnalysis(android.content.Context, java.lang.String)+872)
07-18 11:47:22.738 196-196/? A/DEBUG: #15 pc 0187d1c9 /data/app/com.test-1/oat/arm/base.odex (offset 0xb75000) (int com.test.probing.probe.voiceAnalysis.VoiceAnalyserService.onStartCommand(android.content.Intent, int, int)+292)
07-18 11:47:22.738 196-196/? A/DEBUG: #16 pc 72a4f10f /data/dalvik-cache/arm/system@framework@boot.oat (offset 0x1ed6000)
--------- beginning of system
07-18 11:47:23.199 778-6481/? W/ActivityManager: Force finishing activity com.test/.app.MainActivity
07-18 11:47:23.203 196-196/? A/DEBUG: Tombstone written to: /data/tombstones/tombstone_00
07-18 11:47:23.203 196-196/? E/DEBUG: AM write failed: Broken pipe
我使用开放的微笑作为JNI,我有一个运行分析的服务。 我尝试过不同的Android版本,在不同的架构上,但我遇到了同样的问题。
我不明白第一次运行完美时怎么会发生这种情况。
我很感激有关此事的任何帮助。 先感谢您。
答案 0 :(得分:0)
问题本身不在于openSmile
库。
因为它在第一次尝试时成功运行,在第二次运行时失败。
活动重启后,对本机方法的调用可能会失败。
这可能发生,因为共享库没有重新加载。 System.loadLibrary(String libName)
没有对称方法来手动卸载或重装库。当没有使用它的进程时,Android上的共享库将被卸载。即使活动完成其生命周期并且其onDestroy()
方法被调用,活动的主机进程仍可运行。从活动结束后的Android文档“托管活动的过程可能随时被系统杀死”。我认为当操作系统需要更多内存用于其他任务时会被杀死。
因此,如果旧流程仍然存在,那么共享库也是如此。活动再次启动后,其onCreate()
调用etc,它会附加到同一个运行进程并处理相同的共享库实例。存储所有静态和全局变量的共享库的数据部分仍处于其携带旧值的状态。
现在,为了突出可能的问题,假设我们在本机端有一个Singleton类。我们调用一个本机函数来从activity onCreate
方法创建它。本机方法可能如下所示。
CSomeSingleton* CSomeSingleton::GetInstance()
{
if (m_Instance == NULL)
m_Instance = new CSomeSingleton();
return m_Instance;
}
在activity的onDestroy中,我们调用另一个破坏它的本机方法。假设它看起来像这样。
void CSomeSingleton::FreeInstance()
{
delete m_Instance;
}
在重新启动并重新连接到同一进程后,问题就出现了。 m_Instance不会为NULL,它将指向内存中的无效地址。
有三种变体可以解决这个问题。
根本不要对您的原生对象进行取消初始化(在活动的onDestroy()
中)。当新活动实例将启动时,它将使用有效指针和全局变量附加到正在运行的进程。如果该进程将被时间杀死,它将再次启动,重新加载共享库,重新初始化数据部分。
查找处于不一致状态的全局/静态变量的所有位置。对于上面的例子,将是
void CSomeSingleton :: FreeInstance() { 删除m_Instance; m_Instance = NULL; }
在System.exit(0)
中调用onDestory()
以停止进程,从而卸载共享库。被认为是一种不好的做法,因为您可能还有另一个在该进程中运行的组件,并且此组件可能未处于适当的状态以停止其执行(因为它可能有一些未保存的数据)。
致记:http://choruscode.blogspot.dk/2013/12/on-android-ndk-and-activity-lifecycle.html