“allowed memory size exhausted”错误源于递归无终止条件导致调用栈无限膨胀,耗尽内存(如128mb),典型如阶乘递归遗漏$n==1或$n

“Allowed memory size exhausted” 是递归没设终止条件
这个错误不是参数非法,而是函数调用栈无限膨胀,把 128MB(134217728 bytes)内存全吃光了。典型表现就是写了个阶乘递归,但漏了 $n == 1 或 $n 的返回分支,导致 <code>jiecheng(5) → jiecheng(4) → … → jiecheng(-1) → jiecheng(-2) 一路向下,永不停止。
- 必须显式处理边界:
if ($n (<code>0!和1!都是 1) - 负数要拦截,否则照样进递归:加
if ($n - 别依赖“看起来会停”——PHP 不会自动识别数学逻辑,只认你写的
return
阶乘函数报“参数非法”通常是因为类型或范围越界
PHP 对整数类型宽容,但阶乘函数自己得守规矩。比如传入字符串 "5" 可能侥幸运行,但传 "5.2" 或 null 就大概率触发警告或静默转成 0/1,结果错得离谱;更大的坑是传超大数,比如 10000,即使加了终止条件,也会因递归深度超限(max_execution_time 或 xdebug.max_nesting_level)直接中止。
- 强制类型校验:
if (!is_int($n) || $n ,别只用 <code>!is_numeric() - 加大小限制(如
if ($n > 1000) throw new OverflowException('n too large for safe recursion');) - CLI 下调试时可用
ini_set('xdebug.max_nesting_level', 2000);临时放宽,但生产环境务必用迭代替代递归
用 gmp_fact() 或 bc* 前先确认扩展已启用
想算大数阶乘?别硬刚递归。PHP 自带 gmp_fact()(需 gmp 扩展)或手写 bc 迭代,但前提是扩展真在跑。常见错误是代码里写了 gmp_fact(50),却报 Fatal error: Call to undefined function gmp_fact()——根本不是参数问题,是扩展没开。
- 检查是否加载:
php -m | grep -i gmp(Linux/macOS)或get_loaded_extensions()(Web 环境) - Windows 下确认
php.ini有extension=php_gmp.dll且未被分号注释 -
gmp_fact()只接受非负整数,传字符串会失败;bc系列则要求所有数为字符串格式,比如bcadd('1', '2'),传整数会丢精度
迭代实现比递归更稳,也更容易加防护
几乎所有 PHP 阶乘报错,根源都在控制流失控。而迭代(for/while)天然规避了栈溢出,还能随时插桩检测、中断、记录中间值。
立即学习“PHP免费学习笔记(深入)”;
- 基础安全版:
function factorial($n) {
if (!is_int($n) || $n < 0) {
throw new InvalidArgumentException('n must be non-negative integer');
}
$result = 1;
for ($i = 2; $i <= $n; $i++) {
$result *= $i;
if ($result > PHP_INT_MAX) {
throw new OverflowException('Result exceeds integer limit');
}
}
return $result;
}
- 注意:
$i必须从 2 开始(0!/1!直接返 1),且循环内不能漏掉$i++,否则又变死循环 - 如果真要算上万位阶乘,别碰
int,改用gmp_init()+gmp_mul(),并确保每步都gmp_strval()转出可读结果
最常被忽略的点:错误提示说“内存耗尽”,第一反应不是查参数,而是翻函数有没有 return;说“参数非法”,别急着改输入,先看函数自己有没有做类型断言和范围兜底。PHP 不会替你数学建模,它只执行你写的每一行。











