Quali sono gli errori più comuni associati con il Perl di eval
, che potrebbero rendere si sceglie di utilizzare un modulo come il Try::Tiny
?Quali sono le più comuni insidie quando si utilizza la valutazione di Perl?
risposta
di Perl disponibile in due versioni, stringa eval e il blocco eval. String eval richiama il compilatore per eseguire il codice sorgente. Il blocco eval circonda il codice già compilato in un wrapper che catturerà l'eccezione die
. (stringa eval cattura anche l'eccezione die
, così come eventuali errori di compilazione).
Prova :: Piccolo vale solo per la forma di blocco eval, ma si applica quanto segue per entrambe le forme.
Ogni volta che si chiama eval
, verrà modificato il valore di [email protected]
. Sarà ''
se la valutazione è riuscita o l'errore è stato rilevato dalla valutazione.
Questo significa che ogni volta che si chiama un eval, si cancellerà eventuali messaggi di errore precedenti. Try::Tiny
localizza automaticamente la variabile [email protected]
, in modo che una valutazione di successo non cancellerà il messaggio di una valutazione precedente non riuscita.
L'altra insidia viene dal usando [email protected]
come il controllo per determinare se l'eval riuscito. Un modello comune è:
eval {...};
if ([email protected]) {
# deal with error here
}
Questo si basa su due presupposti, prima che qualsiasi messaggio di errore [email protected]
potrebbe contenere un valore vero (generalmente vero), e che non esiste un codice tra il blocco eval e l'istruzione if.
Visivamente, naturalmente, la seconda è vero, ma se il blocco eval ha creato un oggetto e l'oggetto è andato fuori del campo di applicazione dopo l'eval fallito, allora il metodo dell'oggetto DESTROY
sarà chiamato prima dell'istruzione if
. Se DESTROY
accade di chiamare eval senza localizzazione [email protected]
e riesce, quindi per il momento la sua dichiarazione if
viene eseguito, la variabile [email protected]
verrà cancellata.
La soluzione a questi problemi è:
my $return = do {
local [email protected];
my $ret;
eval {$ret = this_could_fail(); 1} or die "eval failed: [email protected]";
$ret
};
rompendo quella riga per riga a parte, il local [email protected]
crea un nuovo [email protected]
per il blocco che impedisce do
clobbering valori precedenti. my $ret
sarà il valore restituito del codice valutato. Nel blocco eval, viene assegnato $ret
e il blocco restituisce 1
. In questo modo, indipendentemente da cosa, se la valutazione ha esito positivo, verrà restituito true e, in caso di esito negativo, restituirà false. Spetta a voi cosa fare in caso di fallimento. Il codice sopra appena muore, ma potresti facilmente utilizzare il valore di ritorno del blocco eval per decidere di eseguire altro codice.
Poiché l'incantesimo di cui sopra è un po 'noioso, diventa soggetto a errori.L'utilizzo di un modulo come Try::Tiny
ti isola da quei potenziali errori, al costo di alcune chiamate di funzione in più per valutazione. È importante sapere come utilizzare eval correttamente, perché Try::Tiny
non ti aiuterà se devi usare una valutazione di stringa.
Risolto nella versione corrente. – tchrist
Piccola correzione - '$ @' sarà in realtà una stringa vuota anziché undef se non viene lanciata alcuna eccezione. –
@Grant McLean => grazie, ho dovuto ricordare, perché è così che le mie solite offerte Repl con errori: 'perl -Abbiamo 'dire eval, $ @ mentre <>'' –
Le questioni sono spiegati nel Try::Tiny documentation. In breve, essi sono: eval
Oltre alle risposte di cui sopra, vorrei aggiungere ...
- eval è influenzato dal
$SIG{__DIE__}
gestore globale di azione causando a distanza. - è facile per un novizio di confondere
eval BLOCK
eeval STRING
, dal momento che sembrano fare la stessa cosa, ma uno è un buco di sicurezza.
Prova :: Tiny ha le sue insidie, il più grande è che mentre sembra un blocco in realtà è una chiamata di subroutine. Ciò significa che questo:
eval {
...blah blah...
return $foo;
};
e questo:
try {
...blah blah...
return $foo;
};
non fare la stessa cosa. Questi sono disposti nel CAVEATS section of the Try::Tiny docs. Detto questo, lo raccomanderei su eval
.
Sta dicendo che 'eval' è * ancora * insolitamente rotto in 5.14? ** Davvero? ** Sarebbe * estremamente * deludente, perché so che ci è voluto molto lavoro per cercare di rendere 'Try :: Tiny' obsoleto risolvendo qualunque bug sottostante afflitto' eval'.Se questo tentativo fallisce, allora c'è un problema orribile perché 'Try :: Tiny' è ancora semplicemente un modulo CPAN, non core. Se non puoi fare un lavoro vero e affidabile, con il nucleo, allora questa è una situazione inaccettabile. – tchrist
@tchrist Hai dimenticato. A quanto ho capito, 5.14.0 ha risolto una classe di bug che aveva a che fare con le interazioni tra $ @ e la distruzione degli oggetti e in genere reso 'eval {...}; se ($ @) {...} 'più affidabile. Credo che risolva 2 delle 3 cose Try :: Tiny fixes ... e il terzo (un falso $ @) sia piuttosto improbabile. Lascia ancora i punti che ho menzionato. Sarebbe una bella funzionalità 5.16 per fermare '$ SIG {__ DIE __}' da sparare all'interno di un'eval. E chiama il dramma, amico. – Schwern
Chiamare "eval STRING" un "problema di sicurezza" non è solo eccessivamente drammatico; non è nemmeno vero Ho usato 'eval STRING' da quando è apparso perl2 per la prima volta circa ventitré anni fa, posso assicurarti che non ho mai sperimentato alcun cosiddetto" problema di sicurezza "con esso. Certo, i programmatori stupidi possono fare cose stupide con esso, ma questo è vero per quasi tutto. Se esisti in un mondo patologicamente paranoico, dovresti usare la modalità contaminazione e/o compartimenti sicuri. In un mondo normale, 'eval STRING' ottiene molto lavoro utile; guarda il classico programma * rename *. – tchrist
Utilizzare eval sulla funzione X11 potrebbe ancora non è riuscito a mantenere in vita.
Il codice è come
eval {
@win_arrays = GetWindowsFromPid($pid);
};
Lo script viene abbandonato da
X errore di richiesta non riuscita: ...
- 1. Quali sono le insidie più comuni (e le cose da testare) quando si creano app sensibili al fuso orario?
- 2. Quali sono le insidie più comuni della sincronizzazione basata sul timestamp?
- 3. Quali sono le insidie nell'usare sql_variant?
- 4. Quali sono le insidie più comuni per un utente principiante Drupal?
- 5. Quali sono i problemi comuni di sviluppo, le insidie e i suggerimenti?
- 6. Quali sono le insidie dell'impostazione enable_nestloop su OFF
- 7. quali sono le insidie di rendere UnityContainer non thread sicuro?
- 8. C++: quali sono le vulnerabilità più comuni e come evitarle?
- 9. Quali sono le insidie nell'utilizzo di FlexibleContexts e FlexibleInstances?
- 10. Quali sono le insidie del test dopo lo sviluppo?
- 11. Quali sono le insidie durante l'aggiornamento a Java 7
- 12. Quando si usa "require-dev"? Quali sono le dipendenze degli sviluppatori comuni?
- 13. Quali sono le insidie che mi attendono quando migro da CF6.1 a CF8 o Railo3.1?
- 14. Quali sono gli usi comuni di UDP?
- 15. Quali sono i valori predefiniti per le opzioni di arco e codice quando si utilizza nvcc?
- 16. Quali sono gli errori più comuni da evitare durante la codifica di javascript per Internet Explorer?
- 17. Quali sono le cause System.BadImageFormatException quando si costruisce System.Data.SQLite.SQLiteConnection
- 18. Quali sono i modelli di progettazione di servizi Windows comuni?
- 19. JS angolare: quali sono i problemi/le insidie nell'utilizzo di Angular?
- 20. perl stringa di interpolazione quando si utilizza il delimitatore pacchetto
- 21. le variabili globali sono nulle quando si utilizza PHPUnit
- 22. Quali sono i colpevoli comuni della lentezza del TMP
- 23. Aggiunta di un prefisso quando si utilizza join in Perl
- 24. Quali sono le insidie e i trucchi della miscelazione di Objective-C e C?
- 25. Quali sono le librerie Java più importanti?
- 26. Quali sono le applicazioni pratiche degli algoritmi degli antenati più comuni?
- 27. Quali sono le condizioni in cui si può usare un'istruzione 'when' in Perl 5?
- 28. Oracle utilizza la valutazione di cortocircuito?
- 29. Quali sono alcuni pattern di gioco 3D comuni?
- 30. Quali sono alcuni comuni algoritmi di messa a fuoco?
possibile duplicato del [Perché '$ @ 'inaffidabile?] (http://stackoverflow.com/questions/3686857/why-is-untrustworthy), [cosa è rotto sulle eccezioni in Perl?] (http://stackoverflow.com/questions/2165161/) – mob
L'unica ri a meno che tu non usassi il builtin, non stai facendo girare una versione corrente di Perl. – tchrist
@mob - sì, sembra essere la stessa domanda. – Hugh