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 中进行设置。
我按照此处的说明将地址清理器与 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 中进行设置。