You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C++ map中存储ARC管理的Swift/OC对象并避免内存泄漏?

问题

我用C的std::unordered_map管理已加载的区域,每个区域关联一个MTLBuffer,用来存储区域转网格后的几何信息。我想把每个buffer的引用存入这个C map,让区域和关联数据统一存在一个数据结构里,对应的Objective-C++伪代码如下:

struct Region {
    void *buffer;
    // 其他字段
};
std::unordered_map<uint64_t, Region> loaded_regions;
void render_region(Region *region) {
    float vertices[MAX_SIZE];
    unsigned length;

    // ... 生成顶点数据的逻辑

    // 两种创建buffer的方式:
    // 方式一:直接在Objective-C++里创建
    loaded_regions[position].buffer = [device newBufferWithBytes: vertices length: length options: MTLStorageModeShared];

    // 方式二:调用Swift定义的外部函数创建MTLBuffer,再转成裸指针存入map
}

但从map中删除区域时,如下列函数所示:

void delete_region(uint16_t position) {
    Region *region = &loaded_regions[position];

    // ... 其他清理逻辑

    loaded_regions.erase(position);
    // 原伪代码中delete position为错误逻辑
}

在ARC启用的情况下,怎么确保存储的Swift/Objective-C对象引用被正确释放,避免内存泄漏?是不是必须用Swift Dictionary或Objective-C的NSDictionary单独存这些buffer,和管理区域的C++ map分开?因为ARC启用后Xcode不允许直接调用release消息,我不知道该怎么手动释放内存。

解决方案

不需要分开存储,只要在C++结构里正确适配ARC的引用规则即可,核心是让ARC能识别并跟踪OC/Swift对象的引用:

1. 修改Region结构体,使用ARC兼容的指针类型

把原来的void* buffer替换为ARC能识别的强引用类型,这样ARC会自动管理引用计数:

struct Region {
    __strong id<MTLBuffer> buffer; // __strong是默认属性,显式写出更清晰
    // 其他字段
};

赋值时ARC会自动增加引用计数,当Region对象从unordered_map中被移除销毁时,ARC会自动减少引用计数,计数为0时就会释放MTLBuffer。

2. 修正delete_region函数的错误逻辑

原伪代码里的delete position完全错误(position是uint16_t类型的键,不是指针),正确的清理逻辑不需要手动释放buffer,只要确保移除Region即可:

void delete_region(uint16_t position) {
    auto it = loaded_regions.find(position);
    if (it == loaded_regions.end()) {
        return; // 区域不存在,直接返回
    }

    // ... 其他清理逻辑(比如停止使用该buffer的渲染命令)

    // 从map中移除Region,ARC会自动处理buffer的释放
    loaded_regions.erase(it);
}

3. 处理Swift返回的MTLBuffer

如果是调用Swift函数返回MTLBuffer,直接赋值给__strong id<MTLBuffer>类型的变量即可,ARC会自动处理跨语言的引用计数:

// 假设Swift函数已通过@objc暴露给OC++调用
loaded_regions[position].buffer = [SwiftBufferCreator createBufferWithVertices:vertices length:length];

关键注意点

  • 绝对不要用void*存储OC/Swift对象,ARC无法识别裸指针,必然导致内存泄漏。
  • 确保在移除Region前,没有其他地方持有该buffer的强引用,否则即使Region被销毁,buffer也不会被释放。
  • 如果多线程操作这个map,必须加锁保护,避免ARC的引用计数操作出现竞态条件。

内容的提问来源于stack exchange,提问作者CPlus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 15:45:58