PHP FFI内存释放疑问:如何释放FFI::new创建的void*[2]内存
PHP FFI调用C++ DLL时的内存释放问题解决
问题分析
你遇到的zend_mm_heap corrupted错误,根源在于直接释放指针变量而非原始分配的内存块,以及未正确管理FFI分配的持久化内存:
- 通过
$ffi->new("char[...]")创建的字符数组是独立的FFI内存块,但你仅将其指针赋值给$param[0],后续直接对$param[0]调用FFI::free(),相当于释放了一个指针值而非实际内存块的引用。 $param和$cbparam是用persistent=true创建的数组,这类内存不会被PHP自动回收,必须手动释放。
修正后的代码
$ffi = FFI::cdef(" int Do(int methid, int paramlen, void *param[], int cbparam[]); ", "your_dll_path.dll"); // 创建持久化的参数数组和长度数组 $param = $ffi->new("void*[2]", false, true); $cbparam = $ffi->new("int[2]", false, true); $cstr = "test\0"; // 单独保存字符缓冲区的引用,避免丢失内存块地址 $param0_buffer = $ffi->new("char[" . strlen($cstr) . "]", false, true); FFI::memcpy($param0_buffer, $cstr, strlen($cstr)); $param[0] = $param0_buffer; $cbparam[0] = 0; $param2 = 2; $param[1] = $ffi->cast("void*", $param2); $cbparam[1] = 0; // 调用C++函数 $ffi->Do(1, 2, $param, $cbparam); // 正确释放内存:先释放子内存块,再释放父数组 FFI::free($param0_buffer); FFI::free($param); FFI::free($cbparam);
关键注意事项
- 保存原始内存引用:所有通过
$ffi->new(..., true)创建的持久化内存,都要保留原始的FFI\CData对象引用,不能仅通过指针间接释放。 - 释放顺序:先释放嵌套的子内存块(如
$param0_buffer),再释放包含指针的父数组(如$param),避免出现悬空指针导致的堆损坏。 - 值类型参数处理:像
$param2这种直接转换为void*的整数,不需要释放——因为它是值的强制转换,没有分配额外内存,只有通过$ffi->new或FFI::malloc分配的内存才需要手动释放。
内容的提问来源于stack exchange,提问作者jennie
相关产品推荐
相关产品推荐

