Native NE /system/bin/audioserver

本文详细解析了Android系统中AudioFlinger组件的Native异常(NE)问题,揭示了IAudioFlinger对象TimeCheck超时导致audioserver崩溃的根本原因。分析指出,system_server的异常引发了permission服务失效,AudioFlinger在尝试dump操作时未能在规定时间内找到permission服务,从而陷入了无限循环,最终触发了NE。解决方案建议在dump前检查permission服务状态,若服务不可用则直接返回,避免无限循环。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Exception Class: Native (NE)
Exception Type: SIGABRT

Current Executing Process: 
pid: 32235, tid: 32271
/system/bin/audioserver

Backtrace: 
#00 pc 0001cca6 /system/lib/libc.so (abort+58)
#01 pc 00006ccd /system/lib/liblog.so (__android_log_assert+156)
#02 pc 0000e2ef /system/lib/libmedia_helper.so (android::TimeCheck::TimeCheckThread::threadLoop()+270)
#03 pc 0000c08b /system/lib/libutils.so (android::Thread::_threadLoop(void*)+166)
#04 pc 00063305 /system/lib/libc.so (__pthread_start(void*)+22)
#05 pc 0001de69 /system/lib/libc.so (__start_thread+24)

$** *** *** *** *** *** *** *** Exception *** *** *** *** *** *** *** **$


ABI: 'arm'
pid: 23403, tid: 23465, name: TimeCheckThread >>> /system/bin/audioserver <<<
signal 6 (SIGABRT), code --------, fault addr --------
r0 00000000 r1 00005ba9 r2 00000006 r3 00000008
r4 00005b6b r5 00005ba9 r6 a95404a4 r7 0000010c
r8 aac9d943 r9 aa69e2e8 sl 3b9aca00 fp 000fe000
ip ffffb6dc sp a9540490 lr aafece59 pc aafe4ca6 cpsr 200e0030

TimeCheck机制是audioserver里面用于binder in调用超时检测机制,对于audioserver binder in的call不能超过5s

另外一份log中的core-dump

#0 nanosleep () at bionic/libc/arch-arm/syscalls/nanosleep.S:9
No locals.
#1 0xab001244 in sleep (seconds=1) at bionic/libc/upstream-freebsd/lib/libc/gen/sleep.c:58
time_to_sleep =

{tv_sec = 1, tv_nsec = 0}
time_remaining =

{tv_sec = 0, tv_nsec = 847461}
#2 0xaa90d9e2 in android::checkPermission (permission=..., pid=1548, uid=1000) at frameworks/native/libs/binder/IServiceManager.cpp:121
binder =

{m_ptr = 0x0}
startTime = <error reading variable startTime (access outside bounds of object referenced via synthetic pointer)>
#3 0xaa9199d0 in android::PermissionCache::checkPermission (permission=..., pid=1548, uid=1000) at frameworks/native/libs/binder/PermissionCache.cpp:102
t = <optimized out>
granted = false
pc = @0xaa699e70: {<android::Singleton<android::PermissionCache>> = {static sLock = {mMutex = {__private = {0}}}, static sInstance = 0xaa699e70}, mLock = {mMutex = {__private = {0}}}, 
mPermissionNamesPool = {<android::SortedVectorImpl> = {<android::VectorImpl> = {_vptr$VectorImpl = 0xaa9371f0 <vtable for android::SortedVector<android::String16>+8>, mStorage = 0x0, mCount = 0, mFlags = 0, 
mItemSize = 4}, <No data fields>}, <No data fields>}, mCache = {<android::SortedVectorImpl> = {<android::VectorImpl> = { _vptr$VectorImpl = 0xaa93721c <vtable for android::SortedVector<android::PermissionCache::Entry>+8>, mStorage = 0x0, mCount = 0, mFlags = 0, mItemSize = 12}, <No data fields>}, <No data fields>}}
#4 0xaa976904 in android::AudioFlinger::dump (this=0xaa6be000, fd=17, args=...) at frameworks/av/services/audioflinger/AudioFlinger.cpp:486
No locals.
#5 0xaa976d00 in non-virtual thunk to android::AudioFlinger::dump(int, android::Vector<android::String16> const&) () at system/core/libutils/include/utils/Vector.h:251
android::kClientLockedString = "Client lock is taken\n"
android::sMediaLogServiceAsBinder = {m_ptr = 0x0}
android::kHardwareLockedString = "Hardware lock is taken\n"
android::audio_interfaces =

{0xaa9a91c1 "primary", 0xaa9a91c9 "a2dp", 0xaa9a91ce "usb"}
android::sMediaLogService =

{m_ptr = 0x0}
android::kNoEffectsFactory = "Effects Factory is absent\n"
_log_level = 1
android::kDeadlockedString = "AudioFlinger may be deadlocked\n"
FX_IID_AEC_ =

{timeLow = 2068386912, timeMid = 36173, timeHiAndVersion = 4576, clockSeq = 48481, node = "\000\002\245\325\305\033"}
FX_IID_NS_ =

{timeLow = 1488237152, timeMid = 36358, timeHiAndVersion = 4576, clockSeq = 43662, node = "\000\002\245\325\305\033"}
SL_IID_VISUALIZATION_ =

{timeLow = 3832227488, timeMid = 56797, timeHiAndVersion = 4571, clockSeq = 35581, node = "\000\002\245\325\305\033"}
android::sMediaLogOnce = 0
android::AudioFlinger::mScreenState = 0
android::AudioFlinger::mStandbyTimeInNsecs = 3000000000
android::gLock = {mMutex = {__private =

{0}
}}
android::gAudioFlinger =

{m_ptr = 0xaa6be000, m_refs = 0xaa698220}
#6 0xaa9043d8 in android::BBinder::onTransact (this=0xaa6be004, code=<optimized out>, data=..., reply=<optimized out>) at frameworks/native/libs/binder/Binder.cpp:226
fd = <optimized out>
argc = <optimized out>
args = {<android::VectorImpl> = {_vptr$VectorImpl = 0x8e623c08 <vtable for android::Vector<android::String16>+8>, mStorage = 0x0, mCount = 0, mFlags = 0, mItemSize = 4}, <No data fields>}
#7 0xaac893d6 in android::BnAudioFlinger::onTransact (this=<optimized out>, code=<optimized out>, data=..., reply=0xa9d06808, flags=<optimized out>) at frameworks/av/media/libaudioclient/IAudioFlinger.cpp:1473
check =

{static kDefaultTimeOutMs = 5000, mEndTimeNs = 18723149499422}
#8 0xaa9040fa in android::BBinder::transact (this=0xaa6be004, code=1598311760, data=..., reply=<optimized out>, flags=<optimized out>) at frameworks/native/libs/binder/Binder.cpp:129

IAudioFlinger checktime超时 NE:
查看SYS_ANDROID_LOG发现system_server发生NE:
03-08 19:55:14.580 920 938 D AES : ExceptionLog: notify aed, process:system_server pid:920 cause:system_server_crash 
查看audioserver的NE:
03-08 19:55:47.535 23538 23538 D AEE_AED : i, Cls, count, last_time, module 
03-08 19:55:47.535 23538 23538 D AEE_AED : ==================================================================== 
03-08 19:55:47.535 23538 23538 D AEE_AED : 0, 11, 2, 1520501970, system_server 
03-08 19:55:47.536 23538 23538 D AEE_AED : 7, 3, 1, 1520519147, /system/bin/audioserver

结论:IAudioFlinger对象TimeCheck超时引起audioserver NE,根因是system server NE导致“permission” service dead后AudioFlinger dump代码时在5s之内找不到“permission” service引起代码逻辑出现死循环导致超时。
解决方案:“permission” service dead后,在dump之前check service在不再,若不存在,就返回不去dump,避免在dumpAllowed()函数调用出现无限循环sleep导致超时。此方案来规避audioserver的NE。

frameworks/av/services/audioflinger/AudioFlinger.cpp
status_t AudioFlinger::dump(int fd, const Vector<String16>& args){
//add
    sp<IBinder> binder = defaultServiceManager()->checkService(String16("permission"));
    bool isPermissionServiceExist = binder != NULL ? true : false;
    if(!isPermissionServiceExist){
        ALOGI("checkService binder == NULL , permission Service not exist ");
        return UNEXPECTED_NULL;
    }
//add
if (!dumpAllowed()) {
        dumpPermissionDenial(fd, args);
} else {
// get state of hardware lock
        bool hardwareLocked = dumpTryLock(mHardwareLock);
        if (!hardwareLocked) {
            String8 result(kHardwareLockedString);
            write(fd, result.string(), result.size());
.....
.....

 }

}

 

C/C++: ld: error: found local symbol '_edata' in global part of symbol table in file D:/AndroidProject/Application_721_rknn/app_rknn_face_demp/src/main/jniLibs/arm64-v8a\librknn_sunchip.so 我编译出来的库为什么会出现这种情况,我的编译指令是: cmake_minimum_required(VERSION 3.4.1) project(RKFace VERSION 1.0.0) # 设置 C++ 标准 set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) # 基本编译选项 set(CMAKE_C_FLAGS "-Wall -fPIC -O2") set(CMAKE_CXX_FLAGS "-Wall -fPIC -O2") # Android 平台配置 if(CMAKE_SYSTEM_NAME STREQUAL "Android") add_definitions(-DANDROID) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") endif() # 包含目录 include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/include ) # 源文件 set(main_source src/main.cc) # 库文件路径 set(LIBPATH ${CMAKE_CURRENT_SOURCE_DIR}/libs/android) # 链接库 set(LINKS ${LIBPATH}/libRKFace.so ${LIBPATH}/libnva.so ${LIBPATH}/librknnrt.so ) # Android 特定库 if(CMAKE_SYSTEM_NAME STREQUAL "Android") list(APPEND LINKS log c++_shared) endif() # 标准库 list(APPEND LINKS c m dl) # 生成可执行文件 add_executable(rkface.demo ${main_source}) # 链接库 target_link_libraries(rkface.demo ${LINKS}) # 设置安装目录为当前目录下的 install set(CMAKE_INSTALL_PREFIX ${CMAKE_CURRENT_SOURCE_DIR}/install) #生成库 add_library(rknn_sunchip SHARED src/rknn_sunchip.cc) target_include_directories(rknn_sunchip PRIVATE include) target_link_libraries(rknn_sunchip ${LINKS}) # 安装到ABI分层目录 install(TARGETS rknn_sunchip LIBRARY DESTINATION ${LIBPATH}/install/libs/${ANDROID_ABI} ) # 安装可执行文件到 install/bin install(TARGETS rkface.demo RUNTIME DESTINATION bin) # 安装库文件到 install/lib install(FILES ${LIBPATH}/libRKFace.so ${LIBPATH}/libnva.so ${LIBPATH}/librknnrt.so DESTINATION lib ) # 安装头文件到 install/include (如果需要) install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/ DESTINATION include FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp" ),编译脚本是:#!/bin/bash # 编译NVA库为Android .so文件的脚本(优化版本) # 使用方法: ./build_android_optimized.sh [目标ABI] # 检查参数 if [ $# -lt 1 ]; then echo "用法: $0 <目标ABI>" echo "例如: $0 arm64-v8a" echo "支持的ABI: armeabi-v7a, arm64-v8a" exit 1 fi # 参数设置 NDK_PATH=/home/share/work/YML/android-ndk-r19c SRC_PATH=./ TARGET_ABI=$1 BUILD_DIR="${SRC_PATH}/build_android_${TARGET_ABI}" API_LEVEL=24 # 可根据需要调整API级别 PROJECT_ROOT=$(pwd) THIRD_PARTY_PATH="${PROJECT_ROOT}/../000_3rdParty" # OPENCV_PATH="${THIRD_PARTY_PATH}/libopencv/opencv-android-sdk-build" OPENCV_PATH="${THIRD_PARTY_PATH}/libopencv/opencv_android_4.6.0/" # 检查NDK路径是否存在 if [ ! -d "$NDK_PATH" ]; then echo "错误: NDK路径不存在: $NDK_PATH" exit 1 fi # 检查目标ABI是否有效 case $TARGET_ABI in armeabi-v7a) ABI="armeabi-v7a" ARCH_FLAGS="-march=armv7-a -mfpu=neon-vfpv4 -mfloat-abi=hard" ;; arm64-v8a) ABI="arm64-v8a" ARCH_FLAGS="-march=armv8-a" ;; *) echo "错误: 不支持的ABI: $TARGET_ABI" echo "支持的ABI: armeabi-v7a, arm64-v8a" exit 1 ;; esac # 设置优化标志 - 与Linux版本一致 # 设置更保守的优化标志,避免过度优化导致的问题 OPT_FLAGS="-O2 -fno-strict-aliasing -fwrapv -fno-omit-frame-pointer" SECURITY_FLAGS="-fstack-protector-strong -D_FORTIFY_SOURCE=2" VISIBILITY_FLAGS="-fvisibility=hidden -fvisibility-inlines-hidden" # 移除可能导致问题的标志 # EXTRA_FLAGS="-fno-common" # 这个可能在Android上有问题 EXTRA_FLAGS="-fno-common -Wno-unused-command-line-argument" # Android特定的标志 ANDROID_FLAGS="-fPIC -fdata-sections -ffunction-sections" # 链接器标志 - 更保守的设置 LINKER_FLAGS="-Wl,--gc-sections,--as-needed,--no-undefined" # 组合所有标志 ALL_FLAGS="$ARCH_FLAGS $OPT_FLAGS $SECURITY_FLAGS $VISIBILITY_FLAGS $EXTRA_FLAGS $ANDROID_FLAGS" echo "====== 配置信息 ======" echo "NDK路径: $NDK_PATH" echo "源码路径: $SRC_PATH" echo "目标ABI: $TARGET_ABI" echo "构建目录: $BUILD_DIR" echo "API级别: $API_LEVEL" echo "第三方库路径: $THIRD_PARTY_PATH" echo "OpenCV库路径: $OPENCV_PATH" echo "编译优化标志: $ALL_FLAGS" echo "链接器标志: $LINKER_FLAGS" echo "======================" # 创建构建目录 mkdir -p $BUILD_DIR cd $BUILD_DIR # 设置CMake工具链文件路径 TOOLCHAIN_FILE="${NDK_PATH}/build/cmake/android.toolchain.cmake" if [ ! -f "$TOOLCHAIN_FILE" ]; then echo "错误: 无法找到Android CMake工具链文件: $TOOLCHAIN_FILE" exit 1 fi # API级别检查函数 check_api_compatibility() { case $TARGET_ABI in armeabi-v7a) MIN_API=24 ;; arm64-v8a) MIN_API=24 ;; esac if [ $API_LEVEL -lt $MIN_API ]; then echo "错误: OpenCV要求${TARGET_ABI}的最低API级别为${MIN_API}" exit 1 fi } # 在参数检查之后调用 check_api_compatibility # 设置OpenCV配置路径 OPENCV_CONFIG_LOCATIONS=( "${OPENCV_PATH}/sdk/native/jni/abi-${TARGET_ABI}" "${OPENCV_PATH}/sdk/native/jni" "${OPENCV_PATH}/sdk/native" "${OPENCV_PATH}/share/OpenCV" "${OPENCV_PATH}/lib/cmake/opencv4" ) OPENCV_CONFIG_PATH="" for location in "${OPENCV_CONFIG_LOCATIONS[@]}"; do if [ -f "${location}/OpenCVConfig.cmake" ]; then OPENCV_CONFIG_PATH="${location}" echo "找到OpenCV配置文件: ${location}/OpenCVConfig.cmake" break fi done if [ -z "$OPENCV_CONFIG_PATH" ]; then echo "警告: 无法找到OpenCVConfig.cmake文件, 请检查OpenCV路径" echo "将尝试继续配置,但可能会失败..." OPENCV_CONFIG_PATH="${OPENCV_PATH}" fi echo "使用OpenCV配置路径: $OPENCV_CONFIG_PATH" echo "使用CMake工具链文件: $TOOLCHAIN_FILE" # 运行CMake配置 echo "正在配置CMake..." export OpenCV_DIR=$OPENCV_CONFIG_PATH cmake -DCMAKE_TOOLCHAIN_FILE=$TOOLCHAIN_FILE \ -DANDROID_ABI=$ABI \ -DANDROID_PLATFORM=android-$API_LEVEL \ -DANDROID_STL=c++_shared \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_C_FLAGS="$ALL_FLAGS" \ -DCMAKE_CXX_FLAGS="$ALL_FLAGS" \ -DCMAKE_SHARED_LINKER_FLAGS="$LINKER_FLAGS" \ -DCMAKE_EXE_LINKER_FLAGS="$LINKER_FLAGS" \ -DOpenCV_DIR=$OPENCV_CONFIG_PATH \ -DBUILD_SHARED_LIBS=ON \ -DENABLE_LTO=OFF \ -DCMAKE_VERBOSE_MAKEFILE=ON \ -DANDROID_NATIVE_API_LEVEL=$API_LEVEL \ .. # 检查CMake配置是否成功 if [ $? -ne 0 ]; then echo "错误: CMake配置失败" # 提供调试信息 echo "" echo "======= 调试信息 =======" echo "请检查以下几点:" echo "1. OpenCV安装是否完整,确认OpenCV Android SDK路径是否正确" echo "2. 在CMakeLists.txt中,确认OpenCV_DIR路径设置正确" echo "3. 尝试手动查找OpenCVConfig.cmake位置:" echo " find $OPENCV_PATH -name OpenCVConfig.cmake -o -name opencv-config.cmake" echo "4. 确认opencv库对应的ABI版本是否存在:" if [ -d "${OPENCV_PATH}/sdk/native/libs/${ABI}" ]; then echo " ABI库文件存在: ${OPENCV_PATH}/sdk/native/libs/${ABI}" ls -la "${OPENCV_PATH}/sdk/native/libs/${ABI}" else echo " 警告: 没有找到对应ABI的OpenCV库: ${OPENCV_PATH}/sdk/native/libs/${ABI}" fi echo "========================" exit 1 fi # 编译 echo "正在编译..." cmake --build . --config Release -- -j$(nproc) # 检查编译是否成功 if [ $? -ne 0 ]; then echo "错误: 编译失败" exit 1 fi # 创建输出目录 INSTALL_DIR="${BUILD_DIR}/../../install" mkdir -p $INSTALL_DIR/lib/$ABI # 复制生成的库文件 echo "正在安装..." cmake --install . --prefix "$INSTALL_DIR" # 使用strip进一步精简库文件 echo "正在精简库文件..." find $INSTALL_DIR -name "*.so" -exec ${NDK_PATH}/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip --strip-all {} \; echo "编译完成!" echo "库文件位置: $INSTALL_DIR/lib/" ls -la $INSTALL_DIR/lib/ echo "头文件位置: $INSTALL_DIR/include/" ls -la $INSTALL_DIR/include/ echo "生成的库文件列表:" find $INSTALL_DIR -name "*.so" -o -name "*.a" # 显示库文件大小 echo "" echo "库文件大小信息:" find $INSTALL_DIR -name "*.so" -exec du -h {} \;
最新发布
06-08
<think>我们正在处理一个AndroidNDK编译错误:未定义符号`rknn_sunchip_init()`。根据错误信息,链接器(`ld`)在链接过程中找不到这个函数的实现。我们将从原因分析开始,逐步提供解决方案。##原因分析1.**库链接问题(最常见)**:-`rknn_sunchip_init()`函数位于一个名为`librknn_sunchip.so`(或其他名称)的第三方库中,但该库未被正确链接到项目中。-在编译命令中,我们注意到`-lrknn_sunchip`标志存在,表示链接器尝试链接`librknn_sunchip.so`。但是,如果该库文件不存在于链接路径中,或者文件损坏,就会导致此错误。2.**ABI不匹配**:-你正在为`arm64-v8a`架构编译,但提供的`librknn_sunchip.so`可能是其他架构(如`armeabi-v7a`或`x86_64`)的版本。链接器将忽略不匹配的库文件。3.**符号可见性问题**:-`rknn_sunchip_init`函数可能没有以C语言链接的方式导出(即缺少`extern"C"`声明)。这会导致C++的名称修饰(namemangling)问题,使得链接器无法找到原始函数名。4.**库版本不兼容**:-预编译的`librknn_sunchip.so`可能与当前使用的AndroidNDK版本或目标AndroidAPI级别(本例中是android24)不兼容。##解决步骤###1.确认库文件存在且路径正确-在你的项目中,`librknn_sunchip.so`应位于:```src/main/jniLibs/arm64-v8a/librknn_sunchip.so```-**验证步骤**:-检查该路径是否包含正确的`.so`文件。-在文件资源管理器中查看文件大小,以确保文件未损坏(通常至少几十KB)。-如果库文件不存在或损坏,请重新获取该库(从硬件供应商或官方渠道)。###2.检查ABI兼容性-使用`file`命令检查`.so`文件的架构:```bashfilesrc/main/jniLibs/arm64-v8a/librknn_sunchip.so```期望输出:```ELF64-bitLSBsharedobject,ARMaarch64,version1(SYSV),dynamicallylinked,...```如果输出显示为32位(如使用`ARM`而不是`ARMaarch64`)或其他架构,则需要获取正确的64位版本。###3.在CMake中显式添加库路径和链接在`CMakeLists.txt`中添加以下指令以确保链接器能够找到库文件:```cmake#指定库目录link_directories(${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI})#链接到目标target_link_libraries(rknn4j#替换为你的目标名称rknn_sunchip#库名称,即-l后面的部分)```或者使用绝对路径直接链接库文件(如果动态设置路径困难):```cmaketarget_link_libraries(rknn4j${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/librknn_sunchip.so)```###4.验证符号名称-检查函数声明是否正确使用了`extern"C"`(如果该函数是用C++编写的,但在C代码中调用):```cpp#ifdef__cplusplusextern"C"{#endifintrknn_sunchip_init(...);//替换为实际参数#ifdef__cplusplus}#endif```-使用`nm`命令检查库文件是否包含`rknn_sunchip_init`符号:```bashnm-Dsrc/main/jniLibs/arm64-v8a/librknn_sunchip.so|greprknn_sunchip_init```期望输出:```000000000001a120Trknn_sunchip_init```-**注意**:符号名前不能有C++修饰名(如`_Z15rknn_sunchip_initv`是错误的,除非在C++中声明了特殊链接)。###5.版本兼容性检查-确保`librknn_sunchip.so`是针对AndroidNDK版本编译的,并且支持目标API级别(android24)。如果库文件过旧,可能需要联系供应商更新。##其他替代方案如果以上步骤无效,考虑使用**运行时动态加载**库:```cppvoid*handle=dlopen("librknn_sunchip.so",RTLD_LAZY);if(!handle){//处理错误}autofunc=(int(*)(...))dlsym(handle,"rknn_sunchip_init");//使用实际函数原型if(func){func(...);//调用函数}dlclose(handle);```**注意**:这种方法的缺点在于错误发生在运行时而非编译时。##总结大部分`undefinedsymbol`错误由链接配置问题引起。我们建议按照以下顺序检查:1.库文件存在且路径正确✔️2.ABI兼容性✔️3.CMake配置正确✔️4.符号名称正确导出✔️---§§相关问题§§1.为什么AndroidNDK编译时会遇到未定义的引用错误?[^1]2.如何诊断共享库(.so文件)的ABI兼容性问题?3.在CMake中如何管理第三方NDK库的依赖?4.如何为外部库创建符号可见性映射文件?5.运行时动态加载库(dlopen)和静态链接的区别是什么?哪种性能更好?</think> 以下是针对 Android NDK 编译中出现的 `undefined symbol: rknn_sunchip_init()` 错误的原因分析和解决方案: ### 根本原因分析 1. **库链接问题(最常见)** `rknn_sunchip_init()` 函数位于 `librknn_sunchip.so` 中,但以下原因可能导致链接失败: - 库文件路径未正确配置 - CMake 未显式链接该库 - ABI 不匹配(如 arm64-v8a 库误用 armeabi-v7a 链接) 2. **符号可见性问题** 该符号可能被 C++ 名称修饰器修改: ```bash nm librknn_sunchip.so | grep init # 实际符号可能是 _Z18rknn_sunchip_initv 而非 rknn_sunchip_init ``` 因缺少 `extern "C"` 声明导致符号不匹配。 3. **库版本/ABI 不兼容** Rockchip NPU SDK 版本与当前 NDK 不兼容(尤其 Android API 24) 4. **声明与实现分离问题** 参考引用[1]中类似的虚函数表错误,表明可能有未实现的纯虚函数或类方法声明缺失。 --- ### 解决方案 #### 1. 确认库链接配置(关键步骤) 在 CMakeLists.txt 中显式声明依赖: ```cmake # 添加库搜索路径 link_directories(${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}) # 目标显式链接 target_link_libraries(rknn4j rknnrt rga yolov8_pose rknn_sunchip # 确保此库被明确链接 log ) ``` #### 2. 验证符号存在性 使用 NDK 工具检查动态库: ```bash ${NDK_HOME}/toolchains/llvm/prebuilt/windows-x86_64/bin/aarch64-linux-android-nm -D librknn_sunchip.so | grep rknn_sunchip_init ``` 若无输出,说明库中无此符号(需更新 SDK) #### 3. 解决符号命名问题 在 C++ 头文件中添加 `extern "C"` 包装: ```cpp #ifdef __cplusplus extern "C" { #endif int rknn_sunchip_init(...); // 声明与库一致 #ifdef __cplusplus } #endif ``` #### 4. ABI 兼容性检查 在 build.gradle 中确保架构一致: ```groovy android { defaultConfig { ndk { abiFilters 'arm64-v8a' // 必须与库文件目录匹配 } } sourceSets { main { jniLibs.srcDirs = ['src/main/jniLibs'] } } } ``` #### 5. 虚函数表错误修复(参考引用[1]) 若出现类似虚函数表的错误: ```cmake # 确保所有纯虚函数都有实现 target_compile_options(rknn4j PRIVATE "-fno-rtti") # 禁用 RTTI target_link_libraries(rknn4j "-Wl,--no-undefined") # 启用严格符号检查 ``` --- ### 验证流程图 ```mermaid graph TD A[错误出现] --> B{验证库路径} B -->|存在| C[检查符号可见性] B -->|不存在| D[更新SDK库文件] C -->|extern C缺失| E[添加extern声明] C -->|符号存在| F[检查ABI兼容性] F -->|不匹配| G[修改abiFilters] F -->|匹配| H[重新编译验证] ``` ### 预防措施 1. **版本兼容矩阵** | NDK 版本 | Rockchip SDK 版本 | |----------|-------------------| | 23.x | ≥ 1.6.0 | | 21.x | ≥ 1.4.2 | | < 21 | 1.3.x | 2. **符号导出规范** ```cpp #define RKNN_API __attribute__((visibility(''default''))) RKNN_API int rknn_sunchip_init(...); ``` > **注意**:若使用第三方预编译库,建议联系供应商获取与 NDK 23 + Android 10+ 兼容的版本[^1][^2]。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值