目录

NDK工程bad_variant_access崩溃分析和解决

问题现象

HarmonyOS NDK工程运行出现崩溃,报错信息如下:

LastFatalMessage:terminating due to uncaught exception of type std::bad_variant_access: bad_variant_access
Thread name:m.example.application
#00 pc 0000000000199e1c /system/lib/ld-musl-aarch64.so.1(raise+228)(6b9883f518515f73e093bce9a89a2548)
#01 pc 0000000000146f8c /system/lib/ld-musl-aarch64.so.1(abort+20)(6b9883f518515f73e093bce9a89a2548)
#02 pc 00000000000b06c8 /data/storage/el1/bundle/libs/arm64/libc++_shared.so(7d8a9e90f79938a689894d03db6e4557bd538eb3)
#03 pc 0000000000098b38 /data/storage/el1/bundle/libs/arm64/libc++_shared.so(7d8a9e90f79938a689894d03db6e4557bd538eb3)
#04 pc 00000000000af834 /data/storage/el1/bundle/libs/arm64/libc++_shared.so(7d8a9e90f79938a689894d03db6e4557bd538eb3)
#05 pc 00000000000b28e4 /data/storage/el1/bundle/libs/arm64/libc++_shared.so(7d8a9e90f79938a689894d03db6e4557bd538eb3)
#06 pc 00000000000b2860 /data/storage/el1/bundle/libs/arm64/libc++_shared.so(__cxa_throw+124)(7d8a9e90f79938a689894d03db6e4557bd538eb3)

背景知识

在C++17中引入了一个非常有用的类型std::variant,使用前需要包含头文件:

#include <variant>

std::variant是一个类型安全的联合体,可以存储固定集合中的任意类型的值。这使得std::variant成为处理那些可能需要存储不同类型数据的情况的理想选择。

std::variant与union联合体很像,主要区别如下:

问题定位

从崩溃信息中terminating due to uncaught exception of type std::bad_variant_access: bad_variant_access可以看到主要原因在于访问std::variant的时候出的问题。于是全局搜索使用std::variant变量的地方,查看使用方法发现在使用variant的地方没有进行保护,导致出现类型转换错误的时候出现崩溃,示例如下:

using VarObject = std::variant<int, std::string, MyClass>;
VarObject v1 = 42;
VarObject v2 = "Hello";
VarObject v3 = MyClass(100);
...
auto a = std::get<MyClass>(v2); // 转换错误,发生崩溃
...

分析结论

修改建议