Android: ссылка на opencv приводит к SIGBUS (сигнал SIGBUS: неправильное выравнивание) при возникновении исключения - PullRequest
0 голосов
/ 04 декабря 2018

Я должен работать с opencv в проекте Android.Все работало нормально, пока недавно мне не пришлось использовать c ++ exception_ptr.С тех пор использование std::rethrow_exception вызывает SIGBUS (сигнал SIGBUS: неправильное выравнивание).

Я создал минимальный пример для иллюстрации проблемы.Пример приложения ссылается только на opencv 3.4.4, но не использует функцию opencv.Если вы удалите ссылку на opencv в CMakeLists.txt, приложение работает нормально и не падает.Однако, если вы добавите его, приложение вылетит, как только будет вызван собственный метод 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-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

При поиске решения я посмотрел источники 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.

РЕДАКТИРОВАТЬ: Стоит также упомянуть, что ссылки на opencv не влияют, если я используюэтот код напрямую (без jni) в настройках рабочего стола linux (x86_64) (clang, libc ++, opencv3.4.4). Таким образом, мой вывод о том, что это специфическая проблема для Android ...

Есть ли у кого-нибудь идеякак решить эту проблему или что попробовать дальше? Большое спасибо заранее!

1 Ответ

0 голосов
/ 12 декабря 2018

Opencv компилируется во время выполнения gnu, пока вы используете c ++ stl.См. Один STL на приложение .Вам нужно будет либо использовать gnustl (для этого нужно вернуться к ndk 15), либо собрать opencv с помощью c ++ stl.

Чтобы собрать opencv с использованием c ++ _ static, вы можете попытаться выполнить комментарий в багтрекере opencv

cmake -GNinja -DINSTALL_ANDROID_EXAMPLES = ON -DANDROID_EXAMPLES_WITH_LIBS = ON -DBUILD_EXAMPLES = ON -DBUILD_DOCS = OFF -DDCDOOD-OND-OND-OND-ONE-ONE-ONE-INF} /build/cmake/android.toolchain.cmake -DANDROID_TOOLCHAIN ​​= clang "-DANDROID_STL = c ++ _ static" -DANDROID_ABI = x86 -DANDROID_SDK_TARGET = 18 ../opencv

1014 *

make && make install

...