You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP FFI内存释放疑问:如何释放FFI::new创建的void*[2]内存

PHP FFI调用C++ DLL时的内存释放问题解决

问题分析

你遇到的zend_mm_heap corrupted错误,根源在于直接释放指针变量而非原始分配的内存块,以及未正确管理FFI分配的持久化内存:

  1. 通过$ffi->new("char[...]")创建的字符数组是独立的FFI内存块,但你仅将其指针赋值给$param[0],后续直接对$param[0]调用FFI::free(),相当于释放了一个指针值而非实际内存块的引用。
  2. $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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 09:32:19