shared_memory_dict删除条目时正确释放共享内存的方法
问题场景
使用shared_memory_dict库时,定义了持有SharedMemoryDict实例的类A,并用一个全局SharedMemoryDict实例d管理所有A类实例:
from shared_memory_dict import SharedMemoryDict class A: def __init__(self, id): self.smd = SharedMemoryDict(name=id, size=1024) def update(self, i): self.smd[i] = i+1 def clean(self): self.smd.shm.close() self.smd.shm.unlink() del self.smd # 初始化管理字典与A实例 d = SharedMemoryDict(name='dict', size=1024) for i in range(10): d[i] = A(i) for i in range(5): d[i].update(i)
删除d中条目时两种方案均异常:
- 直接执行
del d[0]:A实例内部持有的共享内存未执行close、unlink操作,存在内存泄漏 - 先执行
d[0].clean()再执行del d[0]:触发FileNotFoundError,提示找不到/sm_0共享内存段,报错栈核心逻辑为执行删除操作时,SharedMemoryDict需要反序列化全量字典数据,此时已被unlink的子共享内存无法连接,直接抛错。
问题根因
- SharedMemoryDict默认使用pickle做序列化,每次读取key对应的value时,都会反序列化生成一个新的对象副本,而非返回最初存入的实例。
- 直接删除key时,仅会移除管理字典中存储的序列化字节,不会自动触发A实例的clean逻辑,子共享内存无法被释放。
- 提前调用clean再删key时,子共享内存已被unlink,删除key的流程需要先全量读取、反序列化管理字典内容,反序列化过程会尝试连接已删除的子共享内存,直接触发文件不存在错误。
正确实现方案
1. 加固A类的clean方法
增加重复清理防护,避免重复操作已释放的共享内存触发异常:
class A: def __init__(self, id): self.id = id self.smd = SharedMemoryDict(name=str(id), size=1024) self._is_cleaned = False def update(self, i): if self._is_cleaned: raise RuntimeError("实例已清理,无法执行更新") self.smd[i] = i + 1 def clean(self): if self._is_cleaned: return self.smd.shm.close() self.smd.shm.unlink() self._is_cleaned = True
2. 调整删除操作顺序
严格按照「取实例→删管理字典条目→清理实例关联内存」的顺序执行,禁止提前释放子共享内存:
target_key = 0 # 第一步:取出待删除的A实例,暂存到本地变量 target_instance = d[target_key] # 第二步:从管理字典中删除对应key,此时子共享内存未释放,反序列化、写回流程无异常 del d[target_key] # 第三步:清理暂存实例关联的子共享内存,此时管理字典已无该实例引用,后续不会再尝试连接对应共享内存段 target_instance.clean()
方案说明
- 删除管理字典条目的过程中,子共享内存始终处于可用状态,反序列化流程可以正常连接对应内存段,不会触发FileNotFoundError。
- 管理字典条目删除完成后,字典内已无对应A实例的序列化数据,后续所有对d的读写操作都不会再尝试连接已删除的子共享内存。
- 最后执行clean操作可以完整释放子共享内存的资源,无内存泄漏问题。
内容的提问来源于stack exchange,提问作者phuongnam
相关产品推荐
相关产品推荐

