PHP выполняет синтаксический анализ файла php.ini?

24

Запуск PHP версии 7.1.30 под RHEL 7.7.

Я хочу поднять memory_limit, но не был уверен, что у меня был правильный синтаксис (то есть 256M или 256MB). Поэтому для начала я поставил неверное значение "Hugo" в качестве параметра memory_limit. Проблема в том, что phpinfo () (работает под httpd) буквально содержит строку "Hugo", т.е.

введите описание изображения здесь

Так что это меня несколько беспокоит, что PHP на самом деле не проверяет правильность значений. (Если предоставленное значение было плохим, я бы ожидал, что оно вернется к значению по умолчанию, например)

Может кто-нибудь прокомментировать это - в частности, как вы узнаете, будет ли PHP обеспечивать выполнение вещей (если может быть предоставлена ​​произвольная строка).

Патрик Райнхарт
источник
4
Отличный вопрос.
звон
3
Отсюда: php.net/manual/en/faq.using.php#faq.using.shorthandbytes Я бы предположил, что это то же самое, что и (int) 'HUGO'; // => 0. Который начинает отказывать на моей машине на 2 МБ используемой памяти.
Йоши
@ Йоши, я думаю, ты должен опубликовать свой ответ. Это хорошее объяснение
Максим Федоров
@MaksymFedorov Я колеблюсь, поскольку у меня нет реальной ссылки на мое предположение. Пока это просто наблюдение.
Йоши

Ответы:

19

Смущает то, что настройка выглядит как целое число с некоторым специальным синтаксисом, но внутренне определяется как строка. Затем строка анализируется в отдельной глобальной переменной при каждом изменении значения. Важно отметить, что результат разбора строки на целое число не сохраняется обратно в таблицу настроек, поэтому при вызове phpinfo()вы видите исходный ввод, а не проанализированное значение.

Вы можете увидеть это в источнике:

В конечном итоге поддерживаемый синтаксис определен в zend_atol:

  1. анализирует строку для числового значения, игнорируя любой дополнительный текст
  2. смотрит на последний символ строки, и умножает предыдущее значение , если оно g, G, m, M, k, илиK

Значение без цифр в начале будет проанализировано как ноль. При установке глобальной переменной это установит предел памяти на минимально допустимый, основанный на константе ZEND_MM_CHUNK_SIZE.

Вы можете увидеть эффект, установив предел памяти, затем запустив цикл, который быстро выделяет большой объем памяти и посмотрев, что получится в сообщении об ошибке. Например:

# Invalid string; sets to compiled minimum
php -r 'ini_set("memory_limit", "HUGO"); while(true) $a[]=$a;'
# -> PHP Fatal error:  Allowed memory size of 2097152 bytes exhausted

# Number followed by a string; takes the number
php -r 'ini_set("memory_limit", "4000000 HUGO"); while(true) $a[]=$a;'
# -> PHP Fatal error:  Allowed memory size of 4000000 bytes exhausted

# Number followed by a string, but ending in one of the recognised suffixes
# This finds both the number and the suffix, so is equivalent to "4M", i.e. 4MiB
php -r 'ini_set("memory_limit", "4 HUGO M"); while(true) $a[]=$a;'
# -> PHP Fatal error:  Allowed memory size of 4194304 bytes exhausted
IMSoP
источник
Спасибо @IMSoP за эту великолепную оценку. Стоит ли сообщать о подобных вещах в багтрекер? Я нашел ответ, который phpinfo () генерирует крайне нелогичным. И некоторые выходные данные отладки для того, что делает php, когда он сталкивается с неожиданными значениями, тоже не будут ошибаться.
звон
1
@tink Я думаю, вы могли бы поднять запрос на функцию подать bugs.php.net или отправить сообщение в список рассылки Internals, где происходит большая координация. Я нашел похожий запрос от нескольких лет назад , но, похоже, ответа не было.
IMSoP
Еще раз спасибо, посмотрю на это! :)
звон
0

Прежде всего, сначала нам нужно понять, как PHP.ini работает в процессе интерпретации. memory_limit - это директивы для PHP.

при использовании с функцией PHP вы должны сделать что-то вроде этого ini_set(‘memory_limit’,’256MB’). Таким образом, эта функция временно установит ваше значение для переменной интерпретатора. Если вы посмотрите ближе, то вы можете получить две колонки, одна для локального и один для глобального. Это показывает способность значений для человека соответственно.

Но, когда вы определили для глобального, вы должны установить как суффикс с K, M, G соответственно. Если мы превысим это значение с помощью apache .htaccess, то потребуется то же самое для fpm PHP.

Пранав Бхатт
источник
3
Я хотел бы любезно указать, что ОП не спрашивает, как установить предел памяти :)
Каролис