Newsgroup: it.comp.www.php
Titolo: BUG: da o all'infinito

Volendo stampare i numeri da 0 a 9, faccio questo:
for($i=o;$i<10;$i++) echo $i, "\n";
...ma esplode il computer!
Ciao,
 ___ 
/_|_\  Umberto Salsi
\/_\/  
www.icosaedro.it

 ...ma esplode il computer!
Dalla lettera o al numero 10 c'e` l'infinito... :)
Bye.

 ...ma esplode il computer!
Intanto vedo che al posto del numero 0 (zero) hai messo una lettera "o"
minuscola.
Poi nell'echo, per attaccare due stringhe devi usare il punto, non la
virgola.
Quanto all'esplosione del computer, te l'avevo detto che non dovevi
utilizzare il case del computer per immagazzinare il tritolo.
AS


Prima di postare verifica cosa hai scritto nel codice.

 ...ma esplode il computer!
Soluzione dell'arcano:
- La costante "o" (che non e' zero, ma una lettera) non e' definita. PHP
da' un notice per questo fatto, ma prosegue e considera la stringa "o".
(Ho messo una "o" giusto per rendere la cosa piu' interessante, ma qui
ci potrebbe essere una qualunque altra costante non definita o una stringa
che non inizia con una cifra.)
- L'indice $i viene inizializzato alla stringa "o".
- Quando incremento $i con $i++, PHP vede che $i e' una stringa e
quindi applica un'arcana funzionalita' ereditata dal PERL tale per cui
incrementando "o" si ottengono in sequenza le stringhe p, q, ...,z,
aa, ab, ac, ..., az, ba, bb, ..., bz, ca, cc, ..., zz, aaa, aab, ...
"Funzionalita'" come questa si usano forse una volta nella vita,
ma risultano utilissime per produrre programmi dal funzionamento
stravagante e rendere la vita del programmatore piu' incerta e quindi
piu' interessante.
- Il test $i<10 fallisce sempre perche' l'operatore di confronto trova
che a destra c'e' un intero, e quindi tenta di convertire la stringa $i
in intero, ottenendo sempre 0. Qui sarebbe stato megli se l'interprete
avesse sollevato un warning per via della conversione implicita e il
confronto tra dati di tipo diverso, ma pazienza.
- Il ciclo prosegue all'infinito con $i che diventa una stringa sempre
piu' lunga. Il processo viene stroncato al raggiungimento del timeout
max_execution_time impostato nel php.ini (tipic. 30 secondi).
- Se il valore iniziale fosse stato generato dinamicamente, e fosse
risultato una stringa, questo comportamento produrrebbe un programma
che si blocca in modo inatteso e difficilmente diagnosticabile.
- Insegnamento 1: bisogna sempre attivare la modalita'
    error_reporting  = E_ALL | E_STYLE | E_STRICT
    log_errors = On
in php.ini. In questo caso avrei almeno visto il notice nel log file.
- Insegnamento 2: fare attenzione ai dati non affidabili provenienti
dall'utente, applicando sempre il cast (int) o (string) ai vari $_GET
e $_POST.
- Insegnamento 3: i linguaggi non tipizzati sono famosi per produrre
questi bachi oscuri.
- Perche' tutto questo sbrodolo? Per fare pubblicita' al mio programma
PHPLint, un validatore di sorgenti PHP che, naturalmente, questo problema
lo aveva rilevato subito.
- L'istruzione
   echo $i, "\n";
e' lecita e, anzi, e' il modo migliore per mandare in output diversi
valori.  Le alternative
   echo "$i\n";
   echo ($i . "\n");
   echo ($i\n");
costringono l'interprete a generare dinamicamente una nuova stringa,
con aggravio di lavoro per la gestione della memoria (vabbe', si tratta
di un microsecondo, poca roba :-). Le parentesi tonde non sono quelle
che racchiudono gli argomenti di una funzione (echo e' una istruzione),
ma sono le normali parentesi tonde che si usano nelle espressioni per
alterare l'ordine di precedenza nei calcoli.
