2012-07-25 13 views
9

Ecco una versione ridotta di un codice che causa sia un errore di controllo Range che un errore di overflow, dovrei attivare queste direttive di controllo del compilatore. Capisco perché questo causerebbe un overflow, sulla moltiplicazione di C1, sembra probabile che potrebbe superare il valore massimo del tipo di dati. Ma perché questo dovrebbe anche innescare un errore di verifica del range? La documentazione di Delphi e altri post sullo stack overflow fanno sembrare che gli errori di controllo del range siano di solito per gli accessi di array fuori limite. Ma non sto accedendo a un array sulla linea che sta causando l'errore di controllo dell'intervallo. Forse è sul compito di param1? Ma perché dovrebbe essere un controllo di intervallo e non un errore di overflow, se è così?Causa dell'errore di controllo intervallo (Delphi)

const 
    C1 = 44001; 
    C2 = 17999; 

function fxnName(..other params...; param1: Word): String; 
var 
    someByte: byte; 
begin 
    // some code 
    // by now we're in a loop. the following line is where it breaks to in the debugger: 
    param1 := (someByte + param1) * C1 + C2; 
    // more code 
end; 

Se è rilevante, quando si rompe su quella linea nel debugger, tutti i valori appaiono come previsto, tranne param1, che mostra "identificatore non dichiarato: 'param1'" quando chiedo Delphi per valutarla.

+0

avevo il sospetto è solo perché il controllo di gamma si verifica prima che il controllo di overflow, e una volta che la gamma l'eccezione di controllo viene sollevata e il controllo di overflow non avviene mai. (Non sono sicuro dell'ordine, quindi è solo un sospetto.) –

risposta

17

I documenti relativi Stati dell'area di distribuzione-checking:

Il $ direttiva R abilita o disabilita la generazione di codice di gamma-checking. Nello stato {$ R +}, tutte le espressioni di indicizzazione di stringhe e stringhe vengono verificate entro i limiti definiti e tutte le assegnazioni a variabili scalari e subrange vengono verificate per rientrare nell'intervallo. Se un controllo di intervallo fallisce, viene sollevata un'eccezione ERangeError (o il programma viene terminato se la gestione delle eccezioni non è abilitata).

Quindi il motivo qui è l'assegnazione a un valore scalare, a cui viene assegnato un valore che ha superato l'intervallo superiore.

Vedere anche docwiki Simple Types sugli errori di controllo intervallo nei tipi semplici e nei tipi secondari.

Esempio:

{$R+} // Range check on 
var 
    w1,w2 : word; 
begin 
    w1 := High(word); 
    w1 := w1 + 10; // causes range-check error on assignment to w1 (upper range passed) 
    w2 := 0; 
    w2 := w2 - 10; // causes range-check error on assignment to w2 (lower range passed) 
end; 

Un test sintesi di tutte le combinazioni di $ R e $ Q per tutti i tipi interi indipendenti dalla piattaforma:

  R+Q+ R+Q- R-Q+ 
ShortInt R  R  x 
SmallInt R  R  x 
Integer  O  x  O 
LongInt  O  x  O 
Int64  O  x  O 
Byte  R  R  x 
Word  R  R  x 
LongWord O  x  O 
Cardinal O  x  O 
UInt64  O  x  O 

R = Errore di campo; O = errore di overflow; x = Nothing

e il test è stato (pseudo-codice) con XE2 in modalità a 32 bit:

number := High(TNumber); 
number := number + 1; 
+1

@DavidHeffernan, leggi i documenti, hai appena testato il codice e genera errori di controllo intervallo. È necessario leggere dopo, vale a dire dove si afferma che tutte le assegnazioni a scalari e subrange variabili sono controllate. –

+0

Presumibilmente sarebbe un errore di overflow se il tipo di dati era intero –

+0

@DavidHeffernan Se il calcolo viene eseguito sui tipi 'Integer', sicuro, ma' i: = i + Int64 (1); '* dovrebbe * (non verificato) causare un intervallo di errore quando 'i' è un' Intero' con un valore di 'MaxInt'. – hvd