Native查询麦克风权限状态时崩溃
==================

#### 问题现象

案例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查询当前麦克风的权限状态时，会出现崩溃。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/d5/v3/ZVS2J2NpQfeZln7q9K7ewA/zh-cn_image_0000002628388614.png?HW-CC-KV=V1&HW-CC-Date=20260709T133840Z&HW-CC-Expire=86400&HW-CC-Sign=D4990A3266BF7F396E8C3D499C07E9C1B9017F52D29F751961CB5067A87BC542 "点击放大")

#### 背景知识

napi\_value是一个C的结构体指针，表示一个JavaScript对象的引用。napi\_value持有JS对象，同时，napi\_value受handle\_scope管理，scope中napi\_value持有的JS对象不会被释放；超出scope后，napi\_value将失效，不再持有对应的JS对象。参考：[使用Node-API接口进行生命周期相关开发](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/use-napi-life-cycle#napi_open_handle_scopenapi_close_handle_scope)。

#### 问题定位

根据崩溃日志定位分析NULL pointer dereference原因。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/2e/v3/uGg2hGRyRPWUxniY0FpUCQ/zh-cn_image_0000002628548514.png?HW-CC-KV=V1&HW-CC-Date=20260709T133840Z&HW-CC-Expire=86400&HW-CC-Sign=1B960C16E11A6EA9B8B744D6E6C377849A43E4FBD01BEBF3B2894AE13F99D9B8 "点击放大")

对案例Demo进行debug分析可见abilityAccessCtrlModule获取出来是一个napi\_undefined类型，而status = napi\_get\_named\_property(env,abilityAccessCtrlModule,"createAtManager", &createAtManagerMethod)，期望abilityAccessCtrlModule是一个napi\_value的object类型。

#### 分析结论

*   NULL pointer dereference定位空指针引用位置，需确保在使用对象之前对其进行了非空的初始化。
*   napi\_value类型异常，检查参数类型。

#### 修改建议

1.  确保在使用对象之前对其进行了非空的初始化。
2.  检查参数类型，避免类型异常。
    
    #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); }