我必须在android项目中使用opencv。直到最近我不得不使用c++ exception_ptr,一切都很好。从那时起,std::rethrow_exception的使用会导致SIGBUS (信号SIGBUS:非法对齐)。
我创建了一个很小的例子来说明这个问题。示例应用程序仅链接到opencv 3.4.4,但不使用任何opencv函数。如果您删除CMakeLists.txt中的opencv链接,该应用程序运行良好,不会崩溃。但是,如果添加它,当调用本机方法triggerException()时,应用程序就会崩溃。在我的实现中,如果按下按钮,示例应用程序将调用此方法。
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
为了使用异常和c++17支持,我在android创建的配置中添加了以下行。
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在寻找解决方案时,我查看了opencv源代码(https://github.com/opencv/opencv/blob/master/modules/core/src/parallel.cpp),无意中发现了以下代码片段:
#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如果这改变了opencv的行为,我会理解,但我不明白这会如何影响根本不使用opencv的代码。
编辑:还值得一提的是,如果我在linux (x86_64)桌面设置(clang、libc++、opencv3.4.4)中直接使用这段代码(没有jni),那么链接到opencv没有任何影响。因此,我的结论是这是一个特定于android的问题.
有没有人知道如何解决这个问题,或者下一步该做些什么?提前谢谢!
发布于 2018-12-12 13:37:22
Opencv是在使用c++ stl时用gnu运行时编译的。见每个应用程序一个STL。您需要使用gnustl (为此需要返回到ndk 15 )或使用c++ stl构建opencv。
为了用c++_static构建opencv,您可以尝试遵循opencv bugtracker跟踪器评语
-DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK}/build/cmake/android.toolchain.cmake -GNinja -DINSTALL_ANDROID_EXAMPLES=ON -DANDROID_EXAMPLES_WITH_LIBS=ON -DBUILD_EXAMPLES=ON -DBUILD_DOCS=OFF -DWITH_OPENCL=OFF -DWITH_IPP=ON -DANDROID_TOOLCHAIN=clang "-DANDROID_STL=c++_static“-DANDROID_ABI=x86 -DANDROID_SDK_TARGET=18 ./opencv
紧接着是
制造&&制造安装
https://stackoverflow.com/questions/53603609
复制相似问题