案例Demo:
napi_value global;
napi_get_global(env, &global);
napi_status status;
napi_value abilityAccessCtrlModule;
status = napi_get_named_property(env, global, "abilityAccessCtrl", &abilityAccessCtrlModule);
if(status != napi_ok) {
return;
}
napi_value createAtManagerMethod;
status = napi_get_named_property(env, abilityAccessCtrlModule, "createAtManager", &createAtManagerMethod);
if(status != napi_ok) {
return;
} 如上,在native层调用ArkTS API查询当前麦克风的权限状态时,会出现崩溃。

napi_value是一个C的结构体指针,表示一个JavaScript对象的引用。napi_value持有JS对象,同时,napi_value受handle_scope管理,scope中napi_value持有的JS对象不会被释放;超出scope后,napi_value将失效,不再持有对应的JS对象。参考:使用Node-API接口进行生命周期相关开发。
根据崩溃日志定位分析NULL pointer dereference原因。

对案例Demo进行debug分析可见abilityAccessCtrlModule获取出来是一个napi_undefined类型,而status = napi_get_named_property(env,abilityAccessCtrlModule,"createAtManager", &createAtManagerMethod),期望abilityAccessCtrlModule是一个napi_value的object类型。
#include "napi/native_api.h"
static napi_value CheckUndefined(napi_env env, napi_callback_info info)
{
napi_value res;
napi_value global;
napi_create_double(env, 1, &res);
napi_get_global(env, &global);
napi_status status;
napi_value abilityAccessCtrlModule;
status = napi_get_named_property(env, global, "abilityAccessCtrl", &abilityAccessCtrlModule);
if (status != napi_ok) {
return res;
}
// 检查abilityAccessCtrlModule是否为undefined
napi_valuetype value_type;
napi_typeof(env, abilityAccessCtrlModule, &value_type);
if (value_type == napi_undefined) {
// 这是undefined类型
return res;
}
// 不是undefined类型,继续执行其他操作
napi_value createAtManagerMethod;
status = napi_get_named_property(env, abilityAccessCtrlModule, "createAtManager", &createAtManagerMethod);
if (status != napi_ok) {
return res;
}
napi_create_double(env, 0, &res);
return res;
}
EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports)
{
napi_property_descriptor desc[] = {{"checkUndefined", nullptr, CheckUndefined, nullptr, nullptr, nullptr, napi_default, nullptr}};
napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
return exports;
}
EXTERN_C_END
static napi_module demoModule = {
.nm_version = 1,
.nm_flags = 0,
.nm_filename = nullptr,
.nm_register_func = Init,
.nm_modname = "entry",
.nm_priv = ((void *)0),
.reserved = {0},
};
extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); }