SIGABRT 在使用 Android NDK 的 ASAN 中捕获异常

SIGABRT on caught exception with ASAN with Android NDK

我按照此处的说明将地址清理器与 Android NDK 一起使用:https://developer.android.com/ndk/guides/asan

当抛出异常时,即使处理了异常,我也会收到 SIGABRT。例如,以下代码在使用 ASAN 运行 时抛出异常时导致 SIGABRT,但当 运行 不使用 ASAN 时没有中止。根据我在网上阅读的内容,ASAN 可以处理异常代码。我做错了什么?

#include <jni.h>
#include <exception>

void testThrowException()
{
    try {

        throw std::exception(); // Stops here with SIGABRT
    }
    catch (std::exception& )
    {
    }
}

extern "C"
{

    JNIEXPORT void JNICALL
    Java_com_example_hellojnicallback_MainActivity_doNativeStuff(JNIEnv *env, jobject thiz) {
        testThrowException();
    }

}

这是我的 CMakeLists.txt:

cmake_minimum_required(VERSION 3.4.1)

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer -DANDROID_ARM_MODE=arm -DANDROID_STL=c++_shared")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer -DANDROID_ARM_MODE=arm -DANDROID_STL=c++_shared")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address")
set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} -fsanitize=address")

add_library(hello-jnicallback SHARED
            hello-jnicallback.cpp)

# Include libraries needed for hello-jnicallback lib
target_link_libraries(hello-jnicallback
                      android
                      log)

这是我的 wrap.sh:

#!/system/bin/sh
HERE="$(cd "$(dirname "[=13=]")" && pwd)"
export ASAN_OPTIONS=log_to_syslog=false,allow_user_segv_handler=1,detect_leaks=0
export LD_PRELOAD=$HERE/libclang_rt.asan-i686-android.so
cmd=
shift
os_version=$(getprop ro.build.version.sdk)
if [ "$os_version" -eq "27" ]; then
cmd="$cmd -Xrunjdwp:transport=dt_android_adb,suspend=n,server=y -Xcompiler-option --debuggable $@"
elif [ "$os_version" -ge "28" ]; then
cmd="$cmd -XjdwpProvider:adbconnection -XjdwpOptions:suspend=n,server=y -Xcompiler-option --debuggable $@"
else
cmd="$cmd -XjdwpProvider:adbconnection $@"
fi
exec $cmd

我在 Windows.

上使用来自 Android Studio 运行ning 的 NDK 版本 20.0.5594570

我已经在 Android 模拟器 (x86) 运行ning Android 10 和 Pixel (arm 64) 运行ning Android 9 上进行了测试结果相同。

编辑:根据 Dan Alberts 的回复,此处更新了 CMakeLists.txt 和 wrap.sh。通过这些更改加上将 -DANDROID_ARM_MODE=arm", "-DANDROID_STL=c++_shared" 移动到 build.gradle 它可以正常工作。

add_library(hello-jnicallback SHARED
            hello-jnicallback.cpp)

target_compile_options(hello-jnicallback PUBLIC -fsanitize=address -fno-omit-frame-pointer)
set_target_properties(hello-jnicallback PROPERTIES LINK_FLAGS -fsanitize=address)

# Include libraries needed for hello-jnicallback lib
target_link_libraries(hello-jnicallback
                      android
                      log)
#!/system/bin/sh
HERE="$(cd "$(dirname "[=15=]")" && pwd)"
export ASAN_OPTIONS=log_to_syslog=false,allow_user_segv_handler=1
ASAN_LIB=$(ls $HERE/libclang_rt.asan-*-android.so)
if [ -f "$HERE/libc++_shared.so" ]; then
    # Workaround for https://github.com/android-ndk/ndk/issues/988.
    export LD_PRELOAD="$ASAN_LIB $HERE/libc++_shared.so"
else
    export LD_PRELOAD="$ASAN_LIB"
fi

cmd=
shift
os_version=$(getprop ro.build.version.sdk)
if [ "$os_version" -eq "27" ]; then
cmd="$cmd -Xrunjdwp:transport=dt_android_adb,suspend=n,server=y -Xcompiler-option --debuggable $@"
elif [ "$os_version" -ge "28" ]; then
cmd="$cmd -XjdwpProvider:adbconnection -XjdwpOptions:suspend=n,server=y -Xcompiler-option --debuggable $@"
else
cmd="$cmd -XjdwpProvider:adbconnection $@"
fi
exec $cmd

您是否以某种方式看到该页面的过时副本?您的 wrap.sh 缺少完成这项工作所需的部分(您的 LD_PRELOAD 是错误的)。

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer -DANDROID_ARM_MODE=arm -DANDROID_STL=c++_shared")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer -DANDROID_ARM_MODE=arm -DANDROID_STL=c++_shared")

-DANDROID_STL 不是编译器标志。您需要像文档显示的那样在 build.gradle 中进行设置。