Android中SharedRefBase重载new/delete的原因及std::make_shared崩溃解析
一、重载new/delete运算符的原因
- 统一内存分配逻辑:Android Binder框架有统一的内存管理标准,重载
new/delete并使用std::malloc/std::free,能让SharedRefBase对象的内存分配和框架其他组件保持一致,避免因分配器差异导致的内存碎片化或管理混乱。 - 跨进程兼容性:SharedRefBase是Binder接口的基础类,其对象常需跨进程传递。用标准malloc/free分配的内存,在不同进程环境下都能被正确释放,不会出现因进程专属分配器导致的跨进程内存操作失败。
- 简化调试与监控:统一使用malloc/free后,开发者可以直接利用系统自带的内存调试工具(如Android Studio内存分析器、valgrind)追踪这类对象的内存流向,无需额外适配自定义分配器的调试逻辑。
二、必须使用内部make函数而非std::make_shared的原因
std::make_shared的实现会一次性分配对象内存+shared_ptr控制块内存,将二者放在同一块连续内存中。但它不会调用SharedRefBase重载的operator new,而是使用全局分配器(或std::allocator)分配这块组合内存,这就导致了分配与释放的逻辑不匹配:
- 当shared_ptr引用计数归0时,会用分配组合内存的全局分配器来释放整个内存块,但SharedRefBase对象本身需要通过自身重载的
operator delete(即std::free)来释放。 - Android 12强化了内存操作的校验机制,这种"分配器不匹配"的内存释放操作会被系统检测到,直接触发进程崩溃。
而SharedRefBase内部的make函数,会先调用自身的operator new分配对象内存,再创建shared_ptr时指定对应删除器(绑定SharedRefBase的operator delete),确保内存分配和释放的逻辑完全匹配,从根源避免了内存操作不兼容的问题。
内容的提问来源于stack exchange,提问作者flyzhao
相关产品推荐
相关产品推荐

