Issue
I have a native Android, SDK style library which depends on OpenCV.
In order to avoid conflict when a user uses the library and their own usage with OpenCV, I want to compile OpenCV statically into my library and hide its symbols.
I compiled OpenCV (3.4.13 world
module) statically and used it, along with its 3rd party libraries in my library.
When I try and use my library, and it throws an exception, even if the exception is caught by the user, a SIGABRT
is causing the app to terminate.
This is the stack trace from the 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)
(It also happens if the JNI library uses c++_static
, but in that case the __gxx_personality_v0
and 1 above it come from the libJnilibrary.so
)
If I compile OpenCV as a shared library and link my library against it, then everything works fine.
I've had issues with exceptions in my library before, see this question I asked. I solved it by compiling everything using c++_static
STL. The problem looks similar to this, and indeed I was missing the key function
, but even after adding it, the problem keeps happening.
I looked at the symbols using llvm-readelf -CWs
and noticed that when OpenCV is linked dynamically, in addition to OpenCV symbols, the output contains some ndk and cxxabi symbols which doesn't exist when OpenCV is used statically. I don't know if it's related at all but for example
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)
(All of these are missing when using statically built OpenCV)
I'm using ndk version 21e
(I can't use higher version at the moment because another library uses Bazel
and it only supports up to 21 at the moment)
OpenCV is built with the following flags
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 ..
My libray is compiled using Gradle and Android Studio with these CMake flags
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"
}
}
Solution
The issue wasn't related to the 3rd party or anything like this at all eventually.
I was using NDK version r21e
. Upgrading the NDK to r24
fixed the issue.
It seems that when linking OpenCV
as a shared object, it masked the actual NDK bug by importing or including some of the missing/problematic symbols and when we stopped using it, the error appeared.
Answered By - La bla bla
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.