Symfony 6 Twig调用无参dump()触发内存溢出如何排查解决
Symfony 6 Twig模板无参调用dump()触发内存溢出问题
问题场景
基于Symfony 6开发项目时,在Twig模板内添加{{ dump() }}调试方法会稳定触发Out of Memory异常,即便使用最基础的控制器与模板代码,问题仍可复现。
复现代码与报错
// .../SomeProject/src/Controller/TestController.php class TestController extends AbstractController { public function dashboard(Request $request): Response { return $this->render('dump.html.twig'); } }
{# .../SomeProject/templates/Controller/dump.html.twig #} {{ dump() }}
// 报错信息 Fatal error: Allowed memory size of 17179869184 bytes exhausted (tried to allocate 12882821120 bytes) in ...SomeProject/vendor/twig/twig/src/Extension/DebugExtension.php on line 57 Fatal error: Nesting level too deep - recursive dependency? in ...SomeProject/vendor/symfony/event-dispatcher/EventDispatcher.php on line 163
初步排查与疑问
- 已排查所有服务、控制器可能存在的递归依赖问题,未发现异常
- 疑问:未参与当前请求处理的服务若存在递归依赖,是否会触发该报错?
- 诉求:确认该问题属于Symfony已知bug(是否有对应修复方案),还是项目自身存在错误,以及可采取哪些定位、解决问题的步骤
补充测试结果
针对不同dump调用方式做对照测试,结果如下:
{{ dump() }} // 内存溢出 {{ dump(foo) }} // 正常输出 string(15) "this is as test" {{ foo }} // 最初报变量不存在,修复后可正常输出 {{ _context|keys|dump }} // 报错:Unknown "dump" filter. Did you mean "yaml_dump"? {{ _context|keys|yaml_dump }} // 正常输出:%array% [foo, app] {{ _context|yaml_dump }} // 正常输出:%array% { test: 'this is as test', app: null } {{ dump(_context|keys) }} // 正常输出:array(2) { [0]=> string(4) "test" [1]=> string(3) "app" } {{ dump(_context) }} // 内存溢出
补充说明
此前Variable " foo" does not exist.问题已修复,原因是{{ foo }}前存在非法空格字符,修复后变量可正常输出。
核心问题仍未解决:无参调用dump()无法正常工作。在旧版Symfony 3项目中,dump()可正常输出完整上下文概览,便于开发者快速查看可用变量,调试体验友好。
问题定位结论
- 未参与当前请求处理的服务存在递归依赖不会触发该报错:dump只会遍历当前Twig上下文中已经实例化的对象,未被当前请求初始化的服务不会加载到上下文,不会被遍历。
- 该问题不属于Symfony 6的bug,是版本默认配置变化+对象循环引用共同导致的现象:
- 从测试结果可确认,Twig上下文顶层仅存在
foo、app两个变量,传入简单变量的dump、带递归深度限制的yaml_dump都可正常工作,问题根源是全局app变量持有的请求对象、事件调度器、服务容器等实例内部存在循环引用结构。 - Twig原生debug扩展的dump逻辑基于PHP原生
var_dump实现,Symfony 4+版本默认没有给dump配置递归深度限制,遍历到循环引用时会无限递归,最终耗尽内存;Symfony 3版本dump默认开启了深度限制,因此不会触发该问题。
- 从测试结果可确认,Twig上下文顶层仅存在
可行解决方案
- 临时调试方案:避免直接使用无参
dump(),需要查看上下文可用变量时,先执行{{ _context|keys|yaml_dump }}获取所有变量名,再针对需要调试的单个变量传参调用dump(目标变量名),避开全量递归遍历。 - 永久修复方案:修改项目
config/packages/twig.yaml配置,给Twig的dump功能设置最大递归深度,从根源避免无限递归:
twig: # 保留原有其他配置项不变 debug: '%kernel.debug%' # 新增dump深度限制配置 dump: max_depth: 3
配置生效后,无参dump()遍历到第3层嵌套时会自动截断,不会再触发内存溢出,可恢复Symfony 3版本下的便捷调试体验。
内容的提问来源于stack exchange,提问作者Andrei Herford
相关产品推荐
相关产品推荐

