Python ctypes复制临时缓冲区中结构体失败问题求助
使用ctypes调用黑箱动态链接库时的内存复制问题
我在使用Python的ctypes调用黑箱动态链接库some_library时遇到内存管理问题:调用库接口分配内存、读取数据、解码并获取结构体引用后,释放内存会导致返回的结构体引用失效;但如果不释放内存则会造成内存泄漏,必须在函数返回前完成内存释放。尝试复制结构体后,数据仍然不正确,释放内存后复制的结构体也跟着失效。
原代码
from ctypes import * some_library = CDLL('/usr/lib/black_box.so') # This `Group` comes from `some_library` class Group(Structure): _fields_ = [ ("ChSize", c_uint32*9), ("DataChannel", POINTER(c_float)*9), ("TriggerTimeLag", c_uint32), ("StartIndexCell", c_uint16)] class Thing(Structure): _fields_ = [ ("A", c_uint8*4), ("B", Group*4)] pointer_to_thing = POINTER(Thing)() def get_things(): some_library.allocate_memory() some_library.read_things() things = [] for n in range(some_library.how_many_things_did_your_read()): some_library.decode_next_thing() pointer_to_thing = some_library.give_me_the_thing() thing = pointer_to_thing.contents things.append(thing) some_library.release_memory() return things things = get_things()
这段代码运行失败,因为some_library.give_me_the_thing()返回的是Thing结构体的引用,some_library.release_memory()会释放该结构体所在的内存,导致返回列表中的对象失效。注释release_memory()可正常运行,但必须在函数返回前释放内存。
尝试的复制方法
方法1:使用memmove复制
def get_things(): some_library.allocate_memory() some_library.read_things() things = [] for n in range(some_library.how_many_things_did_your_read()): some_library.decode_next_thing() pointer_to_thing = some_library.give_me_the_thing() thing = pointer_to_thing.contents copy_of_thing = Thing() memmove( addressof(copy_of_thing), addressof(thing), sizeof(Thing), ) things.append(copy_of_thing) some_library.release_memory() return things
返回的Thing数据始终不正确,注释release_memory()则正常。
方法2:使用copy_from_buffer复制
def get_things(): some_library.allocate_memory() some_library.read_things() things = [] for n in range(some_library.how_many_things_did_your_read()): some_library.decode_next_thing() pointer_to_thing = some_library.give_me_the_thing() thing = pointer_to_thing.contents copy_of_thing = Thing.copy_from_buffer(thing) things.append(copy_of_thing) some_library.release_memory() return things
结果与方法1完全相同。
观察到的现象
插入打印语句输出对象地址:
<Thing object at 0x7f8d6f027840> original <Thing object at 0x7f8d6f0278c0> copy -------- <Thing object at 0x7f8d6f027940> original <Thing object at 0x7f8d6f027840> copy -------- <Thing object at 0x7f8d6f0279c0> original <Thing object at 0x7f8d6f027940> copy --------
可见复制的对象地址复用了原对象的地址,推测复制的内存仍由some_library管理,释放后复制的结构体也被销毁。由于some_library是复杂黑箱,无法提供最小可复现示例,寻求解决方法。
内容的提问来源于stack exchange,提问作者user171780
相关产品推荐
相关产品推荐

