HarmonyOS鸿蒙Next中到底是我写的有问题,还是你们的文档代码有问题?做一个代码移植就这么难吗?

HarmonyOS鸿蒙Next中到底是我写的有问题,还是你们的文档代码有问题?做一个代码移植就这么难吗? 简单函数:

char* getAppPackageName(){
    OH_NativeBundle_ApplicationInfo nativeApplicationInfo = OH_NativeBundle_GetCurrentApplicationInfo();
    //获取当前应用的application信息
    char* packageName = nativeApplicationInfo.bundleName;
    //获取存储包名的指针信息
    size_t nameLength = std::strlen(packageName);
    //获取包名的字符长度
    char* packageNameReal = new char[nameLength+1];
    //heap堆上申请一块新内存,来存储包名,并获得新内存的起始地址,这里长度加1是留给'\0'
    for(int i=0;i<nameLength;i++){
        //通过for循环,将package name 复制到新新创建的内存里面
        *(packageNameReal+i) = *(packageName+i);
    }
     *(packageNameReal+nameLength) = '\0';
    //字符结束,一定要加上空字符
    return packageNameReal;
}

调用代码:

static napi_value NAPI_Global_nativeGenerateSecret(napi_env env, napi_callback_info info) {
    // TODO: implements the code;
    bool isDebug = false;
    OH_NativeBundle_IsDebugMode(&isDebug);
    OH_LOG_INFO(LOG_APP, "path: %{public}s", isDebug?"True":"False");
    char* packageName =  getAppPackageName();
    OH_LOG_INFO(LOG_APP, "path: %{public}s", packageName);
    napi_value str;
    napi_create_string_utf8(env, packageName, NAPI_AUTO_LENGTH, &str);
    delete [] packageName;
    return str;
}

在app.json5配置里:

"asanEnabled": true,

在模块的build-profile.json5配置:

"arguments": "-DOHOS_ENABLE_ASAN=ON"

上面的函数就要报错,应用直接崩溃。

但是下面这样设置,屁事没有:

“asanEnabled”: false

“arguments”: “”

报错的内容:

Device info:emulator

Build info:emulator 6.0.0.112(SP3DEVC00E112R4P11)

Fingerprint:c073f772f2da56c0d4b419efbe1f6bcd344f7fa0f5765adc21f73433fcd36343

Timestamp:2025-12-30 19:13:01.393

Module name:com.sshy.aiblindbox

Version:1.0.0

Pid:12500

Uid:20020057

Reason:heap-use-after-free

=================================================================

==appspawn==12500==ERROR: AddressSanitizer: heap-use-after-free on address 0x603001275820 at pc 0x7f536f7467bb bp 0x7ffe86e4fa30 sp 0x7ffe86e4f1f8

READ of size 4 at 0x603001275820 thread T0 (sshy.aiblindbox)

#0 0x7f536f7467ba  (/system/lib64/libclang_rt.asan.so+0x867ba) (BuildId: 7426e27426124e4ca93655f0287fb4c991a96f17)

#1 0x7f531b745294  (/data/storage/el1/bundle/libs/x86_64/libentry.so+0x5294) (BuildId: 5f386d13a75aa7ccac983ebee5bfb4ce5331ce80)

#2 0x7f531b746486  (/data/storage/el1/bundle/libs/x86_64/libentry.so+0x6486) (BuildId: 5f386d13a75aa7ccac983ebee5bfb4ce5331ce80)

#3 0x7f536ac541f0  (/system/lib64/platformsdk/libace_napi.z.so+0x541f0) (BuildId: 762c76a538c75db479d337795e7c7fab)

0x603001275820 is located 0 bytes inside of 20-byte region [0x603001275820,0x603001275834)

freed by thread T0 (sshy.aiblindbox) here:

#0 0x7f536f7a1e7b  (/system/lib64/libclang_rt.asan.so+0xe1e7b) (BuildId: 7426e27426124e4ca93655f0287fb4c991a96f17)

#1 0x7f531b7230b2  (/system/lib64/libbundle_ndk.z.so+0x230b2) (BuildId: c78f124221c904bc126d835538c845fd)

#2 0x7f531b746486  (/data/storage/el1/bundle/libs/x86_64/libentry.so+0x6486) (BuildId: 5f386d13a75aa7ccac983ebee5bfb4ce5331ce80)

#3 0x7f536ac541f0  (/system/lib64/platformsdk/libace_napi.z.so+0x541f0) (BuildId: 762c76a538c75db479d337795e7c7fab)

previously allocated by thread T0 (sshy.aiblindbox) here:

#0 0x7f536f7a1fad  (/system/lib64/libclang_rt.asan.so+0xe1fad) (BuildId: 7426e27426124e4ca93655f0287fb4c991a96f17)

#1 0x7f531b722fae  (/system/lib64/libbundle_ndk.z.so+0x22fae) (BuildId: c78f124221c904bc126d835538c845fd)

#2 0x7f531b746486  (/data/storage/el1/bundle/libs/x86_64/libentry.so+0x6486) (BuildId: 5f386d13a75aa7ccac983ebee5bfb4ce5331ce80)

#3 0x7f536ac541f0  (/system/lib64/platformsdk/libace_napi.z.so+0x541f0) (BuildId: 762c76a538c75db479d337795e7c7fab)

SUMMARY: AddressSanitizer: heap-use-after-free (/system/lib64/libclang_rt.asan.so+0x867ba) (BuildId: 7426e27426124e4ca93655f0287fb4c991a96f17)

Shadow bytes around the buggy address:

0x0c0680246ab0: fd fd fd fa fa fa fd fd fd fa fa fa fd fd fd fa

0x0c0680246ac0: fa fa fd fd fd fa fa fa fd fd fd fa fa fa fd fd

0x0c0680246ad0: fd fa fa fa fd fd fd fa fa fa fd fd fd fa fa fa

0x0c0680246ae0: fd fd fd fa fa fa fd fd fd fa fa fa fd fd fd fa

0x0c0680246af0: fa fa fd fd fd fa fa fa fd fd fd fa fa fa fd fd

=>0x0c0680246b00: fd fa fa fa[fd]fd fd fa fa fa fa fa fa fa fa fa

0x0c0680246b10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa

0x0c0680246b20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa

0x0c0680246b30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa

0x0c0680246b40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa

0x0c0680246b50: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa

Shadow byte legend (one shadow byte represents 8 application bytes):

Addressable: 00

Partially addressable: 01 02 03 04 05 06 07

Heap left redzone: fa

Freed heap region: fd

Stack left redzone: f1

Stack mid redzone: f2

Stack right redzone: f3

Stack after return: f5

Stack use after scope: f8

Global redzone: f9

Global init order: f6

Poisoned by user: f7

Container overflow: fc

Array cookie: ac

Intra object redzone: bb

ASan internal: fe

Left alloca redzone: ca

Right alloca redzone: cb

==appspawn==12500==ABORTING

==appspawn==12500==Process memory map follows:

0x000040a44000-0x000040a48000    /data/storage/el1/bundle/entry.hap

0x00007fff7000-0x00008fff7000    [anon:low shadow]

0x00008fff7000-0x02008fff7000    [anon:shadow gap]

0x02008fff7000-0x0feae3630000    [anon:high shadow]

0x0feae3630000-0x0feae364f000    

0x0feae364f000-0x0feae3650000    [anon:high shadow]

0x0feae3650000-0x0feae366f000    

0x0feae366f000-0x0feae36f5000    [anon:high shadow]

0x0feae36f5000-0x0feae3714000    

0x0feae3714000-0x0feae3716000    [anon:high shadow]

0x0feae3716000-0x0feae3735000    

0x0feae3735000-0x0feae3736000    [anon:high shadow]

0x0feae3736000-0x0feae3755000    

0x0feae3755000-0x0feae3756000    [anon:high shadow]

0x0feae3756000-0x0feae3776000    

0x0feae3776000-0x0feae3777000    [anon:high shadow]

0x0feae3777000-0x0feae3796000    

0x0feae3796000-0x0feae3797000    [anon:high shadow]

0x0feae3797000-0x0feae37b6000    

0x0feae37b6000-0x0feae37b8000    [anon:high shadow]

0x0feae37b8000-0x0feae37d7000    

0x0feae37d7000-0x0feae37d8000    [anon:high shadow]

0x0feae37d8000-0x0feae37f7000    

0x0feae37f7000-0x0feae37f8000    [anon:high shadow]

0x0feae37f8000-0x0feae3817000    

0x0feae3817000-0x0feae3828000    [anon:high shadow]

0x0feae3828000-0x0feae3847000    

0x0feae3847000-0x0feae386f000    [anon:high shadow]

0x0feae386f000-0x0feae388e000    

0x0feae388e000-0x0feae3890000    [anon:high shadow]

0x0feae3890000-0x0feae38af000    

0x0feae38af000-0x0feae38b0000    [anon:high shadow]

0x0feae38b0000-0x0feae38cf000    

0x0feae38cf000-0x0feae38d0000    [anon:high shadow]

0x0feae38d0000-0x0feae38ef000    

0x0feae38ef000-0x0feae3956000    [anon:high shadow]

0x0feae3956000-0x0feae3975000    

0x0feae3975000-0x0feae3976000    [anon:high shadow]

0x0feae3976000-0x0feae3995000    

0x0feae3995000-0x0feae3996000    [anon:high shadow]

0x0feae3996000-0x0feae39b5000    

0x0feae39b5000-0x0feae39b6000    [anon:high shadow]

0x0feae39b6000-0x0feae39d6000    

0x0feae39d6000-0x0feae39d7000    [anon:high shadow]

0x0feae39d7000-0x0feae39f6000    

0x0feae39f6000-0x0feae39f7000    [anon:high shadow]

0x0feae39f7000-0x0feae3a16000    

0x0feae3a16000-0x0feae3b18000    [anon:high shadow]

0x0feae3b18000-0x0feae3b37000    

0x0feae3b37000-0x0feae3b38000    [anon:high shadow]

0x0feae3b38000-0x0feae3b57000    

0x0feae3b57000-0x0feae3b58000    [anon:high shadow]

0x0feae3b58000-0x0feae3b77000    

0x0feae3b77000-0x0feae3b87000    [anon:high shadow]

0x0feae3b87000-0x0feae3ba7000    

0x0feae3ba7000-0x0feae3ba8000    [anon:high shadow]

0x0feae3ba8000-0x0feae3bc7000    

0x0feae3bc7000-0x0feae3bc8000    [anon:high shadow]

0x0feae3bc8000-0x0feae3be7000    

0x0feae3be7000-0x0feae3be9000    [anon:high shadow]

0x0feae3be9000-0x0feae3c08000    

0x0feae3c08000-0x0feae4481000    [anon:high shadow]

0x0feae4481000-0x0feae4490000    

0x0feae4490000-0x0feae4491000    [anon:high shadow]

0x0feae4491000-0x0feae44a1000    

0x0feae44a1000-0x0feae471f000    [anon:high shadow]

0x0feae471f000-0x0feae473e000    

0x0feae473e000-0x0feae473f000    [anon:high shadow]

0x0feae473f000-0x0feae475e000    

0x0feae475e000-0x0feae4760000    [anon:high shadow]

0x0feae4760000-0x0feae47bf000    

0x0feae47bf000-0x0feaeaefe000    [anon:high shadow]

0x0feaeaefe000-0x0feaeafaf000    

0x0feaeafaf000-0x100050cc4000    [anon:high shadow]

0x100050cc4000-0x100050dc3000    

0x100050dc3000-0x10007fff8000    [anon:high shadow]

0x55c51f92f000-0x55c51f93d000    /system/bin/appspawn

0x55c51f93d000-0x55c51f94e000    /system/bin/appspawn

0x55c51f94e000-0x55c51f94f000    /system/bin/appspawn

0x55c51f94f000-0x55c51f950000    /system/bin/appspawn

0x55c52150c000-0x55c52150d000    [heap]

0x55c52150d000-0x55c521517000    [heap]

0x600000000000-0x602000000000    [anon:SizeClassAllocator]

0x602000000000-0x602001260000    [anon:SizeClassAllocator: region data]

0x602001260000-0x602e00000000    [anon:SizeClassAllocator]

0x602e00000000-0x602e00010000    [anon:SizeClassAllocator: freearray]

0x602e00010000-0x603000000000    [anon:SizeClassAllocator]

0x603000000000-0x603001300000    [anon:SizeClassAllocator: region data

更多关于HarmonyOS鸿蒙Next中到底是我写的有问题,还是你们的文档代码有问题?做一个代码移植就这么难吗?的实战教程也可以访问 https://www.itying.com/category-93-b0.html

3 回复

你写的有问题  不难啊

更多关于HarmonyOS鸿蒙Next中到底是我写的有问题,还是你们的文档代码有问题?做一个代码移植就这么难吗?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


鸿蒙Next的API和架构与之前版本有差异,直接移植代码可能不兼容。请检查是否使用了已废弃的接口或未适配新框架。建议查阅最新的HarmonyOS Next官方文档,确认API调用方式。

根据你提供的代码和报错信息,问题出在 getAppPackageName 函数的内存管理上。AddressSanitizer (ASAN) 检测到了 heap-use-after-free 错误,即内存被释放后又被访问。

根本原因分析:

  1. OH_NativeBundle_GetCurrentApplicationInfo 返回的结构体nativeApplicationInfo.bundleName 指针指向的内存是由系统API内部管理的。你的代码假设这个指针指向的是一个你可以安全持有并随后进行 strlen 操作的、以空字符结尾的字符串。
  2. 生命周期问题OH_NativeBundle_ApplicationInfo 结构体(及其内部的 bundleName 指针)很可能在 OH_NativeBundle_GetCurrentApplicationInfo 函数调用结束后就失效了,或者其内存所有权有特殊的规则。你的代码在获取该指针后,又在其可能失效的上下文中使用它(进行字符串复制),导致了释放后使用。

错误复现路径(推测):

  • 系统API OH_NativeBundle_GetCurrentApplicationInfo 在栈上或某个临时内存区填充了 OH_NativeBundle_ApplicationInfo 结构体,bundleName 指向该区域内的一个字符串。
  • 你的函数返回后,该临时内存区被回收或标记为可释放。
  • 随后,你的 std::strlen(packageName)napi_create_string_utf8 尝试读取这块已释放的内存,触发ASAN报错。

解决方案:

不要直接复制 bundleName 指针,而是应该在 OH_NativeBundle_GetCurrentApplicationInfo 调用后,立即将字符串内容复制到你自己管理的内存中。查阅HarmonyOS NDK文档,确认 OH_NativeBundle_ApplicationInfo 及其字段的确切生命周期和内存所有权。通常,对于这类返回字符串指针的API,需要立即进行深拷贝。

一个更安全的 getAppPackageName 函数实现示例如下(需根据实际API调整):

char* getAppPackageName() {
    OH_NativeBundle_ApplicationInfo nativeApplicationInfo = OH_NativeBundle_GetCurrentApplicationInfo();
    // 立即获取原始指针和长度
    const char* bundleName = nativeApplicationInfo.bundleName;
    if (!bundleName) {
        return nullptr;
    }
    // 计算长度(假设bundleName是有效的C字符串)
    size_t nameLength = std::strlen(bundleName);
    // 分配新内存
    char* packageNameReal = new char[nameLength + 1];
    // 复制字符串内容
    std::strcpy(packageNameReal, bundleName);
    // 返回新分配的内存,调用者负责释放
    return packageNameReal;
}

关键点:

  • bundleName 被当作一个临时指针,仅用于立即的 strlenstrcpy 操作。
  • 所有后续操作都使用你自己分配的 packageNameReal 内存。
  • 调用者(NAPI_Global_nativeGenerateSecret)在 napi_create_string_utf8 后使用 delete[] 释放内存是正确的。

当关闭ASAN时,内存错误可能未被立即检测到,程序看似“正常”,但这掩盖了潜在的崩溃风险。ASAN报告准确地指出了问题所在:代码存在对已释放堆内存的访问。修复内存管理逻辑即可解决此问题。

回到顶部