必须显式调用imagedestroy()销毁GD图像资源,因其内存由C malloc分配、不走PHP引用计数,脚本结束也不会自动释放;循环处理、资源链、中转画布及CLI常驻进程均需严格配对销毁。

PHP用GD库生成图片时,不手动销毁资源,内存就真不还——哪怕脚本执行完,RSS也不回落。这不是GC没起作用,是GD底层用C malloc分配的内存,压根不走PHP引用计数体系。
imagedestroy() 必须显式调用,不能靠脚本结束自动回收
GD创建的图像资源(如 imagecreatefromjpeg()、imagecreatetruecolor() 返回值)属于“外部资源”,Zend内存管理器不跟踪它们。脚本退出时只会释放PHP变量层引用,而图像占用的真实内存仍挂在进程里。
- 循环批量生成缩略图?每轮末尾必须加
imagedestroy($img),否则100张图可能吃掉几百MB RSS - 函数内创建又返回图像资源?调用方负责销毁,不是创建方“一走了之”
- 用
is_resource($img)判断再销毁,避免对 null 或已销毁变量重复调用报 Warning
销毁顺序影响资源残留:先子后父,别漏中间产物
图像处理链中常产生多个资源(原图、缩略图、水印图、临时画布),销毁顺序错乱会导致部分资源永远悬空。
- 示例中
$thumbnail = imagescale($im, 100, 100)创建新资源,它和$im是独立的,都要单独imagedestroy() - 如果先
imagedestroy($im)再操作$thumbnail,没问题;但反过来,若误以为销毁原图就等于释放所有衍生资源,就会漏掉$thumbnail - 使用
imagecopyresampled()等函数生成的新图像,哪怕只用一次,也得销毁
别混淆“清空画布”和“销毁资源”
imagefill($img, 0, 0, $white) 或重绘背景只是改像素内容,资源本身还在内存里占着位置;imagedestroy() 才是真正归还内存。
立即学习“PHP免费学习笔记(深入)”;
- 需要复用同一画布多次绘制?用
imagefill()清屏即可,不用销毁重建 - 确定不再需要这张图(比如已输出到文件或响应体)?立刻
imagedestroy(),别等“后面可能还要用” - 创建空白画布做中转(如合成多图)?中转完成立即销毁,别留着当“全局缓存”
最易被忽略的是:CLI常驻进程(如Swoole Worker)里,一次漏掉 imagedestroy(),内存泄漏会持续累积,直到进程被 max_requests 强制重启——但这不是解决方案,只是兜底补救。



















