Ctypes结构和指针在Python对象删除时会自动释放内存吗?

11 投票
1 回答
6094 浏览
提问于 2025-04-16 09:09

在使用Python的CTypes时,有一种叫做结构体的东西,它可以让你在Python中复制C语言的结构体。同时,还有指针对象,它可以根据内存地址创建一个复杂的Python对象,并且可以用来在C代码和Python之间传递对象。

我在文档或者其他地方找不到的信息是,当一个包含结构体的Python对象被删除时,这个结构体是从C代码返回的指针中解引用出来的(也就是说,C函数为这个结构体分配了内存),那么原来的C结构体的内存会被释放吗?如果不会,那该怎么做呢?

另外,如果这个结构体里面还有指向其他数据的指针,而这些数据也是由C函数分配的内存,那么删除这个结构体对象会释放它里面指针指向的内存吗?(我对此表示怀疑)如果不会,那又该怎么处理呢?我尝试从Python中调用系统的“free”来释放结构体中的指针,但这让我Python崩溃了。

换句话说,我有一个通过C函数调用填充的结构体:

class PIX(ctypes.Structure):
    """Comments not generated
    """
    _fields_ = [
        ("w", ctypes.c_uint32),
        ("h", ctypes.c_uint32),
        ("d", ctypes.c_uint32),
        ("wpl", ctypes.c_uint32),
        ("refcount", ctypes.c_uint32),
        ("xres", ctypes.c_uint32),
        ("yres", ctypes.c_uint32),
        ("informat", ctypes.c_int32),
        ("text", ctypes.POINTER(ctypes.c_char)),
        ("colormap", ctypes.POINTER(PIXCOLORMAP)),
        ("data", ctypes.POINTER(ctypes.c_uint32))
    ]

我想从Python代码中释放它所占用的内存。

1 个回答

13

内存没有被释放,因为Python不知道该如何释放它。我们来看看这两个函数:

void testfunc1(PIX *pix)
{
    static char staticBuffer[256] = "static memory";
    pix->text = staticBuffer;
}

void testfunc2(PIX *pix)
{
    pix->text = (char *)malloc(32);
    strcpy(pix->text, "dynamic memory");
}

用法是这样的:

pix1, pix2 = PIX(), PIX()
mylib.testfunc1(ctypes.byref(pix1))
mylib.testfunc2(ctypes.byref(pix2))

然后在某个时刻,pix1pix2 失去了作用域。当这种情况发生时,内部指针不会有任何变化——如果它们指向动态内存(这里的pix2就是这样,但pix1不是),那么你就得自己负责释放这部分内存。

解决这个问题的正确方法是,如果你在C代码中分配了动态内存,你应该提供一个相应的函数来释放这部分内存。例如:

void freepix(PIX *pix)
{
    free(pix->text);
}


pix2 = PIX()
mylib.testfunc2(ctypes.byref(pix2))
...
mylib.freepix(ctypes.byref(pix2))

撰写回答