O PHP faz alguma análise no arquivo php.ini?

24

Executando o PHP Versão 7.1.30 no RHEL 7.7.

Estou querendo aumentar o memory_limit, mas não tinha certeza se tinha a sintaxe correta (ou seja, 256M ou 256MB). Então, para começar, coloquei um valor ruim "Hugo" como a configuração memory_limit. O problema com isso é o resultado de phpinfo () (executado em httpd) literalmente ter a string "Hugo" no lugar, ou seja:

insira a descrição da imagem aqui

Portanto, isso me preocupa um pouco que o PHP não faça nenhuma verificação de sanidade para o (s) valor (es). (Se o valor fornecido for ruim, esperaria que ele retornasse ao padrão, por exemplo)

Alguém pode comentar sobre isso - em particular, como você sabe se o PHP aplicará as coisas (se uma string arbitrária puder ser fornecida).

Patrick Rynhart
fonte
4
Excelente pergunta.
tink
3
A partir disso: php.net/manual/en/faq.using.php#faq.using.shorthandbytes Eu diria que é o mesmo que (int) 'HUGO'; // => 0. O que começa a falhar na minha máquina com 2 MB de memória usada.
Yoshi
Para o registro, a sintaxe correta émemory_limit 256M .
Tigger 27/01
@ Yoshi Eu acho que você deve divulgar sua resposta. É uma boa explicação
Maksym Fedorov 27/01
@MaksymFedorov Estou hesitante porque não tenho nenhuma referência real à minha suposição. Por enquanto é apenas uma observação.
Yoshi

Respostas:

19

A coisa confusa aqui é que a configuração se parece com um número inteiro com alguma sintaxe especial, mas é definida internamente como uma string. A sequência é analisada em uma variável global separada sempre que o valor é alterado. Fundamentalmente, o resultado da análise da string em um número inteiro não é salvo de volta na tabela de configurações; portanto, quando você chama phpinfo(), vê a entrada original, não o valor analisado.

Você pode ver isso na fonte:

A sintaxe suportada é finalmente definida em zend_atol, que:

  1. analisa a sequência para um valor numérico, ignorando qualquer texto adicional
  2. olha para o último caractere da string, e multiplica o valor anterior se é g, G, m, M, k, ouK

Um valor sem dígitos no início será analisado como zero. Ao definir a variável global, isso definirá o limite de memória para o mínimo permitido, com base na constante ZEND_MM_CHUNK_SIZE.

Você pode ver o efeito definindo o limite de memória e executando um loop que aloca rapidamente uma grande quantidade de memória e vendo o que sai na mensagem de erro. Por exemplo:

# 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
fonte
Obrigado @IMSoP por essa ótima avaliação. Alguém deveria relatar esse tipo de coisa em qualquer tipo de rastreador de bugs? Acho a resposta que phpinfo () gera altamente contra-intuitivo. E alguma saída de depuração para o que o php faz quando encontra valores inesperados também não seria bom.
tink
11
Acho que você pode enviar uma solicitação de recurso no bugs.php.net ou enviar uma mensagem para a lista de discussão da Internals, onde é a maior parte da coordenação. Encontrei um pedido semelhante de vários anos atrás , mas parece não ter tido nenhuma resposta.
IMSoP 29/01
Mais uma vez obrigado, vamos olhar para isso! :)
tink
0

Primeiro, precisamos entender como o PHP.ini funciona no caminho do fluxo de trabalho de interpretação. memory_limit é diretivas para PHP.

ao usar com a função PHP, você deve fazer algo assim ini_set(‘memory_limit’,’256MB’). Portanto, essa função definirá temporariamente seu valor para a variável intérprete. Se você vir mais de perto, poderá obter as duas colunas Uma é para o Local e Uma é para o global. Isso mostra a capacidade dos valores para o indivíduo, respectivamente.

Porém, quando você definiu para global, precisa definir como sufixo K, M, G, respectivamente. Se excedermos esse valor usando o apache .htaccess, será necessário o mesmo para o PHP fpm.

Pranav Bhatt
fonte
3
Gostaria de salientar que o OP não está perguntando como definir o limite de memória :)
Karolis