为何无法在C中释放Python ctypes创建的内存?报错code=3221226356
ctypes内存释放错误分析与解决
问题重现
运行以下Python代码调用自定义DLL时,出现code=3221226356错误:
Python代码
import ctypes import os # Load the DLL script_dir = os.path.dirname(os.path.abspath(__file__)) dll_path = os.path.join(script_dir, "test.dll") funcs = ctypes.CDLL(dll_path) funcs.free_arr.argtypes = [ctypes.POINTER(ctypes.c_int)] ids = [1, 2, 3] ids_arr = (ctypes.c_int * len(ids))(*ids) funcs.free_arr(ids_arr)
对应的C代码
#include <stdio.h> #include <stdlib.h> void free_arr(int* ids) { free(ids); }
错误原因
(ctypes.c_int * len(ids))(*ids)创建的数组内存是Python解释器堆区分配的,并非通过C标准库的malloc/calloc函数分配。而C的free函数只能释放由C标准库分配的内存,直接释放Python管理的内存会破坏堆结构,触发堆损坏错误(code=3221226356对应Windows的STATUS_HEAP_CORRUPTION)。
Python是否会自动释放该数组
会。ids_arr是Python的ctypes数组对象,当它的引用计数归0时(比如变量被删除、代码块执行完毕),Python的垃圾回收机制会自动回收它占用的内存,无需手动调用C的free。
让C控制释放数组内存的正确方式
要让C负责内存生命周期,必须由C分配内存,再交给Python使用,最后由C释放:
修改后的C代码
#include <stdio.h> #include <stdlib.h> // C端分配内存并复制数据 int* create_arr(int* data, int length) { int* arr = (int*)malloc(length * sizeof(int)); if (arr == NULL) return NULL; for (int i = 0; i < length; i++) { arr[i] = data[i]; } return arr; } // C端释放内存 void free_arr(int* ids) { free(ids); }
修改后的Python代码
import ctypes import os # Load the DLL script_dir = os.path.dirname(os.path.abspath(__file__)) dll_path = os.path.join(script_dir, "test.dll") funcs = ctypes.CDLL(dll_path) # 声明函数参数和返回值类型 funcs.create_arr.argtypes = [ctypes.POINTER(ctypes.c_int), ctypes.c_int] funcs.create_arr.restype = ctypes.POINTER(ctypes.c_int) funcs.free_arr.argtypes = [ctypes.POINTER(ctypes.c_int)] ids = [1, 2, 3] # 创建临时ctypes数组用于给C传递初始化数据 temp_arr = (ctypes.c_int * len(ids))(*ids) # 调用C函数分配内存并复制数据 c_arr = funcs.create_arr(temp_arr, len(ids)) # 示例:使用C分配的数组 for i in range(len(ids)): print(f"元素{i}: {c_arr[i]}") # 调用C函数释放内存 funcs.free_arr(c_arr)
这样内存的分配和释放都由C标准库管理,不会出现堆损坏问题。
内容的提问来源于stack exchange,提问作者NiceGuySaysHi
相关产品推荐
相关产品推荐

