Issue
I have to work with opencv in an android project. Everything worked fine until I recently had to use c++ exception_ptr as well.
Since then, the use of std::rethrow_exception
causes a SIGBUS (signal SIGBUS: illegal alignment).
I created a minimal example to illustrate the problem. The example application only links to opencv 3.4.4 but does not use any opencv function. If you remove the linking to opencv in CMakeLists.txt
the app works fine and doesn't crash. If you add it however, the app will crash as soon as the native method triggerException()
is called.
In my implementation the example application calls this method if a button is pressed.
native-lib.cpp:
#include <jni.h>
#include <string>
#include <exception>
/*
* code based on: https://en.cppreference.com/w/cpp/error/exception_ptr
*/
std::string handle_eptr2(std::exception_ptr eptr)
{
try {
if (eptr) {
std::rethrow_exception(eptr);
}
} catch (const std::exception &e) {
return "Caught exception \"" + std::string(e.what()) + "\"\n";
}
return "Something went wrong";
}
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_user_exceptiontest_MainActivity_triggerException(
JNIEnv *env,
jobject /* this */) {
std::exception_ptr eptr;
try {
std::string().at(1); // this generates an std::out_of_range
} catch(...) {
eptr = std::current_exception(); // capture
}
std::string res = handle_eptr2(eptr);
return env->NewStringUTF(res.c_str());
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.4.1)
set(OPENCV_DIR $ENV{HOME}/lib/OpenCV-android-sdk/sdk )
include_directories(${OPENCV_DIR}/native/jni/include )
add_library( native-lib
SHARED
src/main/cpp/native-lib.cpp)
find_library( log-lib
log)
target_link_libraries(
native-lib
# Removing the following line will make everything work as expected (what() message is returned)
${OPENCV_DIR}/native/libs/${ANDROID_ABI}/libopencv_java3.so # <--- critical line
${log-lib})
build.gradle
To use exceptions and c++17 support, I added the following lines to the configuration that is created by android-studio.
externalNativeBuild {
cmake {
arguments '-DANDROID_TOOLCHAIN=clang',
'-DANDROID_STL=c++_shared'
cppFlags "-std=c++1z -frtti -fexceptions"
}
}
Stacktrace:
<unknown> 0x004c4e47432b2b01
___lldb_unnamed_symbol15856$$libopencv_java3.so 0x0000007f811c4a58
_Unwind_Resume_or_Rethrow 0x0000007f811c4fc8
__cxa_rethrow 0x0000007f81181e50
__gnu_cxx::__verbose_terminate_handler() 0x0000007f811b1580
__cxxabiv1::__terminate(void (*)()) 0x0000007f81181c54
std::terminate() 0x0000007f81181cc0
std::rethrow_exception(std::exception_ptr) 0x0000007f802db2cc
handle_eptr2(std::exception_ptr) native-lib.cpp:35
::Java_com_example_user_exceptiontest_MainActivity_triggerException(JNIEnv *, jobject) native-lib.cpp:58
While searching for a solution I looked at the opencv sources (https://github.com/opencv/opencv/blob/master/modules/core/src/parallel.cpp) and stumbled upon this code snippet:
#ifndef CV__EXCEPTION_PTR
# if defined(__ANDROID__) && defined(ATOMIC_INT_LOCK_FREE) && ATOMIC_INT_LOCK_FREE < 2
# define CV__EXCEPTION_PTR 0 // Not supported, details: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58938
I'd understand if this changes the behavior of opencv, but I don't get how this might influence code that does not use opencv at all.
EDIT: It is also worth mentioning that linking to opencv has no impact if I use this code directly (without jni) in a linux (x86_64) desktop setting (clang, libc++, opencv3.4.4). Thus, my conclusion that it is an android specific problem...
Does anyone has an idea how to solve that issue or what to try next? Thanks a lot in advance!
Solution
Opencv is compiled with gnu runtime while you are using c++ stl. See One STL per app. You will need to either use gnustl (you will need to go back to ndk 15 for that) or build opencv with c++ stl.
In order to build opencv with c++_static you can try to follow comment in opencv bugtracker
cmake -GNinja -DINSTALL_ANDROID_EXAMPLES=ON -DANDROID_EXAMPLES_WITH_LIBS=ON -DBUILD_EXAMPLES=ON -DBUILD_DOCS=OFF -DWITH_OPENCL=OFF -DWITH_IPP=ON -DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK}/build/cmake/android.toolchain.cmake -DANDROID_TOOLCHAIN=clang "-DANDROID_STL=c++_static" -DANDROID_ABI=x86 -DANDROID_SDK_TARGET=18 ../opencv
Followed by
make && make install
Answered By - Dmitrii Z.
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.