You need to enable JavaScript to run this app. 如何正确使用PyObject_Malloc/Realloc避免内存泄漏及指针释放报错
优惠活动
大模型
产品
解决方案
定价
更多

如何正确使用PyObject_Malloc/Realloc避免内存泄漏及指针释放报错

PyObject内存分配接口的正确使用方法

问题背景

参考CPython源码对PyObject_Realloc的说明:

对于非空指针p,调用PyObject_Realloc(p, 0)时,既不会返回NULL值,也不会释放p指向的内存空间。

据此认为该函数不会主动释放内存,在排查内存泄漏时编写了如下调整内存大小的逻辑:

PyLongObject *new = (PyLongObject *) PyObject_Realloc(obj, new_size);
if (new == NULL) {
  return PyErr_NoMemory();
}
if (new != obj) {
  PyObject_Free(obj);
}
obj = new;

修改后程序触发malloc报错:pointer being freed was not allocated,需要明确搭配使用PyObject_Malloc、PyObject_Realloc的正确流程,避免内存泄漏。

报错根源

代码中手动调用PyObject_Free(obj)的逻辑是触发报错的核心原因。
PyObject_Realloc的常规场景语义与标准C库realloc完全一致:当申请的新内存大小大于0时,函数会自动完成原内存块的尺寸调整、内容拷贝、原内存块回收的全流程,原指针的内存所有权完全由函数内部接管,调用者无需手动释放原指针。
此时再对已经被函数内部回收的旧指针调用释放接口,属于二次释放操作,会触发分配器的校验逻辑,抛出“指针未被分配就被释放”的错误。

易混淆的边界规则

你看到的文档说明仅适用于申请内存大小为0的特殊场景:

  • 当传入非空原指针,且申请大小为0时,函数不会释放原指针指向的内存,会直接返回原指针地址,这是唯一需要手动处理原内存的realloc场景
  • 其他所有常规尺寸的调整场景下,函数都会自动完成原内存的回收,不存在“不主动释放内存”的问题

正确操作流程

  • 内存分配:直接调用PyObject_Malloc(申请大小),将返回的有效指针存入对应的变量
  • 尺寸调整:直接调用PyObject_Realloc(原有指针, 新的申请大小),将返回的新指针直接替换原有变量的值,无需手动释放旧指针。正确的调整代码示例:
    PyLongObject *new = (PyLongObject *) PyObject_Realloc(obj, new_size);
    if (new == NULL) {
      return PyErr_NoMemory();
    }
    obj = new;
    
  • 常规内存释放:对当前持有的有效指针调用PyObject_Free即可,无需追溯指针的历史变更过程
  • 0尺寸场景处理:当需要将内存块收缩到0大小时,不能依赖realloc的自动回收逻辑,需要直接调用PyObject_Free释放内存,并将指针置空避免野指针

内存泄漏规避要点

  • 严格遵守分配器配对规则:所有通过PyObject_Malloc、PyObject_Realloc分配的内存,必须使用PyObject_Free释放,禁止和标准C库的malloc、realloc、free混用,否则会因内存块元数据不兼容触发报错或泄漏
  • 非0尺寸的realloc流程中,不要手动释放原指针,避免二次释放
  • 释放内存时直接操作当前持有的有效指针,不要依赖边界场景下的自动回收逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.28 15:06:03