OpenHarmony开发者论坛

标题: lazyforeach快速修改数据的时候崩溃 [打印本页]

作者: chinabosh    时间: 2024-6-13 16:14
标题: lazyforeach快速修改数据的时候崩溃
[md]### 【问题描述】

1. 介绍问题现象和发生的背景
   应用需要快速显示一些数据
2. 相关的代码(请勿使用截图)

   ```
   export class DataSource implements IDataSource {
     private listeners: DataChangeListener[] = [];

     private origin: string[]
     private dataChange: () => void

     constructor(data: string[]) {
       this.origin = data
     }

     totalCount(): number {
       return this.origin.length - 1
     }

     getData(index: number): any {
       return this.origin[index]
     }

     onDataChange(listener: () => void) {
       this.dataChange = listener
     }

     registerDataChangeListener(listener: DataChangeListener): void {
       if (this.listeners.indexOf(listener) < 0) {
         console.info('add listener');
         this.listeners.push(listener);
       }
     }

     unregisterDataChangeListener(listener: DataChangeListener): void {
       const pos = this.listeners.indexOf(listener);
       if (pos >= 0) {
         console.info('remove listener');
         this.listeners.splice(pos, 1);
       }
     }

     // 通知LazyForEach组件需要重载所有子组件
     notifyDataReload(): void {
       this.listeners.forEach(listener => {
         listener.onDataReloaded();
       })
       this.dataChange()
     }

     // 通知LazyForEach组件需要在index对应索引处添加子组件
     notifyDataAdd(index: number): void {
       this.listeners.forEach(listener => {
         listener.onDataAdd(index);
       })
       this.dataChange()
     }

     // 通知LazyForEach组件在index对应索引处数据有变化,需要重建该子组件
     notifyDataChange(index: number): void {
       this.listeners.forEach(listener => {
         listener.onDataChange(index);
       })
       this.dataChange()
     }

     // 通知LazyForEach组件需要在index对应索引处删除该子组件
     notifyDataDelete(index: number): void {
       this.listeners.forEach(listener => {
         listener.onDataDelete(index);
       })
       this.dataChange()
     }

     // 通知LazyForEach组件将from索引和to索引处的子组件进行交换
     notifyDataMove(from: number, to: number): void {
       this.listeners.forEach(listener => {
         listener.onDataMove(from, to);
       })
       this.dataChange()
     }
   }

   this.mInputDataSource = new DataSource(this.mInputData)
   setInterval(() => {
         let data = Date.now().toString()
         if (this.mInputData.length == 100) {
           this.mInputData.pop()
           this.mInputDataSource.notifyDataDelete(this.mInputData.length)
         }
         this.mInputData.unshift(data)
         this.mInputDataSource.notifyDataAdd(0)
         this.mInputDataSource.notifyDataReload()
       }, 50)

   List({ scroller: this.scroller }) {
               LazyForEach(this.inputData, (item: string, index: number) => {
                 ListItem() {
                    Text(item)
                      .fontSize(16)
                      .fontColor(Color.White)
                 }.padding({ top: 5, bottom: 5 })
                 .reuseId('input list')
               }, (item: string, index: number) => {
                 return item + index.toString()
               })
             }.attributeModifier(new SettingListAttribute())
             .padding(20)
             .layoutWeight(1)
             .cachedCount(10)
   ```
3. 运行结果、错误截图

   ![image.png](https://forums-obs.openharmony.c ... knlm3nhvmymfykx.png "image.png")

   ![image.png](https://forums-obs.openharmony.c ... xxqw0lllcqcslus.png "image.png")
4. 我尝试过的解决方法和结果

   尝试过降低更新数据频率,但是只是让崩溃来的晚一些
5. 我想要达到的结果

   不崩溃

### 【运行环境】

硬件:rk3588
ROM版本:OpenHarmony 4.1.7.5
DevEvoStudio版本:4.1.3.501
SDK版本:11(full-sdk)
[/md]
作者: chinabosh    时间: 2024-6-14 10:31
经过排查发现,不是lazyforeach的问题!!!
是其他地方错误使用了napi_create_external_arraybuffer,如下:
  1.      napi_finalize finalize_cb;
  2.     if (napi_ok !=
  3.         napi_create_external_arraybuffer(
  4.             env, buffer_data, mDataSize, finalize_cb, nullptr, &ret)) {
  5.         LOGE("ArraybufferType", "napi_create_external_arraybuffer failed");
  6.         return nullptr;
  7.     }
复制代码


按照我的推测:lazyforeach在快速更新列表的时候,会较快的触发内存回收的操作,而napi_create_external_arraybuffer这里的finalize_cb没有执行内存回收操作,导致data成野指针,从而导致内存回收时崩溃!!!
正确使用napi_create_external_arraybuffer如下
  1. if (napi_ok !=
  2.         napi_create_external_arraybuffer(
  3.             env, buffer_data, mDataSize, [](napi_env env, void *data, void *hint) { free(data); }, nullptr, &ret)) {
  4.         LOGE("ArraybufferType", "napi_create_external_arraybuffer failed");
  5.         return nullptr;
  6.     }
复制代码





欢迎光临 OpenHarmony开发者论坛 (https://forums.openharmony.cn/) Powered by Discuz! X3.5