SIGABRT当在Android中静态使用第三方库时从.so抛出异常



我有一个原生Android, SDK样式库,依赖于OpenCV。

为了避免当用户使用库和他们自己使用OpenCV时发生冲突,我想将OpenCV静态编译到我的库中并隐藏其符号。

我静态编译OpenCV (3.4.13world模块)并使用它,以及它在我的库中的第三方库。

当我尝试使用我的库时,它抛出一个异常,即使该异常被用户捕获,SIGABRT正在导致应用程序终止。

这是来自logcat

的堆栈跟踪

A/libc: Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 24115 (.test), pid 24115 (.test)
...
A/DEBUG: backtrace:
A/DEBUG:       #00 pc 0000000000051948  /apex/com.android.runtime/lib64/bionic/libc.so (abort+168) (BuildId: 931371c1098ffd5adc489b9ff4da8e82)
A/DEBUG:       #01 pc 00000000000b2ba0  /data/app/~~gc4ZOfzcr7C0hRfmsieCtQ==/com.example.test-sx2ESCfGCsi3lXPZWnk9nA==/base.apk!libc++_shared.so (BuildId: ece72a2ebc3774a1be9fd21271258acd3bcdfaa7)
A/DEBUG:       #02 pc 00000000000aec8c  /data/app/~~gc4ZOfzcr7C0hRfmsieCtQ==/com.example.test-sx2ESCfGCsi3lXPZWnk9nA==/base.apk!libc++_shared.so (__gxx_personality_v0+348) (BuildId: ece72a2ebc3774a1be9fd21271258acd3bcdfaa7)
A/DEBUG:       #03 pc 00000000004dd2dc  /data/app/~~gc4ZOfzcr7C0hRfmsieCtQ==/com.example.test-sx2ESCfGCsi3lXPZWnk9nA==/base.apk!libmylib.so (BuildId: 790f2880373cb985055ab9b7b2efc48b1afb82fd)
A/DEBUG:       #04 pc 00000000004dd7e4  /data/app/~~gc4ZOfzcr7C0hRfmsieCtQ==/com.example.test-sx2ESCfGCsi3lXPZWnk9nA==/base.apk!libmylib.so (BuildId: 790f2880373cb985055ab9b7b2efc48b1afb82fd)
A/DEBUG:       #05 pc 0000000000170600  /data/app/~~gc4ZOfzcr7C0hRfmsieCtQ==/com.example.test-sx2ESCfGCsi3lXPZWnk9nA==/base.apk!libmylib.so (mylib::TestClass::TestClass(char const*, char const*)+908) (BuildId: 790f2880373cb985055ab9b7b2efc48b1afb82fd)
A/DEBUG:       #06 pc 000000000000c5d0  /data/app/~~gc4ZOfzcr7C0hRfmsieCtQ==/com.example.test-sx2ESCfGCsi3lXPZWnk9nA==/base.apk!libJnilibrary.so (BuildId: 7f3605ea8cb95dc87864e3df22f6b77b46c2e592)
A/DEBUG:       #07 pc 000000000000c3b8  /data/app/~~gc4ZOfzcr7C0hRfmsieCtQ==/com.example.test-sx2ESCfGCsi3lXPZWnk9nA==/base.apk!libJnilibrary.so (BuildId: 7f3605ea8cb95dc87864e3df22f6b77b46c2e592)
A/DEBUG:       #08 pc 000000000000c308  /data/app/~~gc4ZOfzcr7C0hRfmsieCtQ==/com.example.test-sx2ESCfGCsi3lXPZWnk9nA==/base.apk!libJnilibrary.so (Java_com_example_lib_Engine_cxxInit+56) (BuildId: 7f3605ea8cb95dc87864e3df22f6b77b46c2e592)
A/DEBUG:       #09 pc 00000000002d7644  /apex/com.android.art/lib64/libart.so (art_quick_generic_jni_trampoline+148) (BuildId: 2b417e2566f5eb686666666b6ee952ea)

(如果JNI库使用c++_static,也会发生这种情况,但在这种情况下,它上面的__gxx_personality_v0和1来自libJnilibrary.so)

如果我将OpenCV编译为共享库并将我的库链接到它,那么一切都可以正常工作。

我以前在库中遇到过异常问题,参见我问的这个问题。我通过使用c++_staticSTL编译一切来解决它。问题看起来类似于此,确实我错过了key function,但即使在添加它之后,问题仍然发生。

我查看了使用llvm-readelf -CWs的符号,并注意到当OpenCV动态链接时,除了OpenCV符号外,输出还包含一些ndk和cxxabi符号,这些符号在OpenCV静态使用时不存在。我不知道它们之间是否有联系但是例如

110: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND std::uncaught_exception()
...
201: 0000000000000000     0 OBJECT  GLOBAL DEFAULT  UND vtable for __cxxabiv1::__vmi_class_type_info
...
231: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND std::__ndk1::to_string(unsigned int)

(当使用静态构建的OpenCV时,所有这些都缺失)

我正在使用ndk版本21e(我现在不能使用更高的版本,因为另一个库使用Bazel,它目前只支持最多21)

OpenCV是用以下标志构建的

cmake -DCMAKE_BUILD_TYPE=Release -DINSTALL_ANDROID_EXAMPLES=OFF -DANDROID_EXAMPLES_WITH_LIBS=OFF -DANDROID_ABI="arm64-v8a" 
-DBUILD_EXAMPLES=OFF -DBUILD_DOCS=OFF -DWITH_OPENCL=OFF -DBUILD_ANDROID_PROJECTS=OFF -DBUILD_ANDROID_EXAMPLES=OFF -DANDROID_ARM_NEON=1 
-DANDROID_STL=c++_static -DANDROID_PLATFORM=android-21 -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake" 
-DBUILD_SHARED_LIBS=OFF -DBUILD_FAT_JAVA_LIB=OFF -DBUILD_JAVA=OFF -DINSTALL_CREATE_DISTRIB=ON -DINSTALL_ANDROID_EXAMPLES=OFF -DBUILD_opencv_objdetect=OFF
-DBUILD_opencv_video=ON -DBUILD_opencv_videoio=ON -DBUILD_opencv_features2d=ON -DBUILD_opencv_flann=OFF -DBUILD_opencv_highgui=ON -DBUILD_opencv_ml=OFF 
-DBUILD_opencv_photo=OFF -DBUILD_opencv_python=OFF -DBUILD_opencv_shape=OFF -DBUILD_opencv_stitching=OFF -DBUILD_opencv_superres=OFF -DBUILD_opencv_ts=OFF 
-DBUILD_opencv_videostab=OFF -DBUILD_ANDROID_PROJECTS=OFF -DBUILD_opencv_world=ON -DBUILD_opencv_dnn=OFF -DBUILD_opencv_core=ON -DBUILD_opencv_imgcodecs=ON 
-DBUILD_opencv_imgproc=ON -DBUILD_opencv_calib3d=ON -GNinja -DCMAKE_INSTALL_PREFIX=../install -DBUILD_ZLIB=1 -DWITH_PROTOBUF=OFF -DWITH_QUIRC=OFF ..

我的库是使用Gradle和Android Studio编译的,带有这些CMake标志

externalNativeBuild {
cmake {
cppFlags "-std=c++17 -static-openmp -fopenmp -fexceptions -frtti -Wno-unused-command-line-argument -Wl,-s"
cppFlags "-Wl,--exclude-libs,libc++_static.a -Wl,--exclude-libs,libc++abi.a"
arguments "-DANDROID_STL=c++_static", "-DANDROID_ARM_NEON=TRUE"
}
}

这个问题最终与第三方或任何类似的东西无关。

我使用NDK版本r21e。升级NDK到r24修复了这个问题。

似乎当链接OpenCV作为共享对象时,它通过导入或包含一些缺失/有问题的符号来掩盖实际的NDK错误,当我们停止使用它时,错误出现了。

最新更新