NDK调用Native方法异常闪退
=================

#### 问题现象

NDK工程中，调用Native方法报异常。

*   报错信息为符号找不到：
    
    Symbol not found: xxx, version: nul
    
*   报错信息为方法所属的对象未定义：
    
    TypeError: Cannot read property add of undefined
    
*   报错信息为系统侧的符号找不到：
    
    xxx.so: \_\_fd\_chk: symbol not found
    
    或者：
    
    xxx: Symbol not found
    
    同时应用闪退。
    

#### 背景知识

*   [使用命令行CMake构建NDK工程](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/build-with-ndk-cmake)：在Linux/MAC环境，使用命令行构建库。
*   [使用Node-API跨语言调用](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/using-napi-interaction-with-cpp)：ArkTS和Native C++跨语言调用的规范和指导。
*   [版本变更说明：匿名内存执行权限变更](https://developer.huawei.com/consumer/cn/doc/harmonyos-releases/changelogs-for-all-apps-b031)：禁止申请匿名内存或修改匿名内存。

#### 问题定位

*   根据缺失的符号，查看对应的SO是否被打包到HAP中正确的路径下，并且该符号在SO中对外可见。
*   查看对应的SO是否存在其他依赖库，依赖库是否正确引入。
*   使用到的SO文件是否是通过HarmonyOS工具链编译的。
*   跨语言调用接口和声明文件是否正确编写。
*   参照版本变更说明，查看SO对应的源码中，有没有版本新增禁止的行为，如申请匿名内存或修改匿名内存。
*   排查SDK版本与工程机版本是否匹配。

#### 分析结论

可能导致问题的原因为：

*   SO名称或版本不匹配，不是使用HarmonyOS工具链编译的或未打包到正确的lib目录下。
*   SO依赖其他SO，依赖的SO没有同步引入。
*   缺少了跨语言调用接口模块和声明文件，接口调用路径不同。
*   使用了被禁止的方法，如申请或修改匿名内存。
*   SDK版本与工程版本不匹配。

#### 修改建议

*   修改代码，确保未使用被禁止的方法。
*   使用HarmonyOS工具链编译库及其依赖的库，确认需要调用的接口对外可见。
*   将编译的SO放在NDK工程指定路径，参照指导编写跨语言接口模块并在ArkTS侧导入和正确调用。
*   为解决不同版本工程机与SDK之间的兼容性问题，建议工程机版本与IDE/SDK版本配套使用，见[配套关系](https://developer.huawei.com/consumer/cn/doc/harmonyos-releases/overview-allversion)。

#### 常见FAQ

Q：Native引用libusb\_ndk.z.so或者libusb\_serial\_ndk.z.so，运行后闪退，这是什么原因导致的？

A：libusb\_ndk.z.so或者libusb\_serial\_ndk.z.so只能用于PC端开发用户态驱动，手机形态暂不支持使用。

Q：Native项目中引用的两个har包同时依赖libc++\_shared.so，导致符号冲突闪退怎么解决？

A：在项目的CMakeLists.txt文件中添加"arguments": "-DOHOS\_STL=c++\_static"选项，使得项目静态依赖libc++\_shared.a，可以避免冲突。

Q：在C++侧对结构体属性进行赋值操作时发生崩溃，但在运行时打开地址分析选项就可以正常运行，是什么原因？

A：代码中存在结构体重名导致，可以通过修改结构体名称解决。

Q：使用dlopen动态加载沙箱路径下的SO文件报错是什么原因？

A：HarmonyOS的安全机制（基于MUSL-LDSO的命名空间隔离）限制了动态库的加载路径。默认的命名空间(moduleNs\_default)仅允许加载安装包内（HAP包内）的库或系统库，禁止直接加载应用沙箱数据目录（如/files、/cache）下的二进制文件，以防止代码注入等安全风险。

建议将.so文件直接打包在HAP包中。将SO文件放置在工程的libs/或src/main/cpp/libs目录下（取决于构建配置），随应用一起安装。此时系统会自动将其路径加入允许列表，使用dlopen("[libname.so](http://libname.so/)")即可加载。

Q：多模块工中通过配置[nativeLib](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/ide-hvigor-cpp#section15889929155720)的[filter](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/ide-hvigor-cpp#section17675528161517)属性设置加载SO文件的优先级，实际运行没有生效时什么原因？

A：实际使用时需要指明依赖的模块名，参考[Native侧跨HAR/HSP模块调用Native方法](https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-cross-module-reference#section470062115417)。