2012-07-25 22 views
9

Aquí hay una versión condensada de algún código que causa tanto un error de comprobación de rango como un error de desbordamiento, si enciendo esas directivas de verificación de compilador. Entiendo por qué esto causaría un desbordamiento, en la multiplicación de C1, parece probable que pueda exceder el valor máximo del tipo de datos. ¿Pero por qué esto también desencadenaría un error de Range-check? La documentación de Delphi y otras publicaciones sobre el desbordamiento de la pila hacen que parezca que los errores de comprobación de rango son generalmente para los accesos de matriz que están fuera de los límites. Pero no estoy accediendo a una matriz en la línea que está diciendo que está causando el error de verificación de rango. Tal vez es en la asignación a param1? Pero, ¿por qué sería eso un control de rango y no un error de desbordamiento, si es así?Causa del error de comprobación de rango (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; 

Si es relevante, cuando se rompe en esa línea en el depurador, todos los valores se ven como se esperaba, excepto param1, lo que demuestra "identificador no declarado: 'param1'" cuando pido Delphi para evaluarla.

+0

Me sospecho que es sólo porque la prueba de alcance se produce antes de la verificación de desbordamiento, y una vez que el rango se genera una excepción de cheque, la verificación de desbordamiento nunca ocurre. (No estoy seguro del orden, por lo tanto, es solo una sospecha.) –

Respuesta

17

Los documentos sobre los estados del área de comprobación:

La Directiva R $ activa o desactiva la generación de código de comprobación de rango. En el estado {$ R +}, todas las expresiones de matrices e indización de cadenas se verifican dentro de los límites definidos, y se verifica que todas las asignaciones a variables escalares y de subintervalos estén dentro del rango. Si falla una comprobación de rango, se genera una excepción ERangeError (o el programa finaliza si la gestión de excepciones no está habilitada).

Así que la razón aquí es la asignación a un valor escalar, que se le entrega a un valor que ha pasado el rango superior.

Consulte también docwiki Simple Types sobre errores de comprobación de rango en tipos simples y tipos de subrango.

Ejemplo:

{$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; 

Una prueba de resumen de todas las combinaciones de $ R y Q $ para todos los tipos de enteros independientes de la plataforma: = Error de área

  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; O = error de desbordamiento; x = Nada

Y la prueba fue (pseudo-código) con XE2 en el modo de 32 bits:

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

@DavidHeffernan, lea los documentos, acabo de probar el código y genera errores de comprobación de rango. Debe leer después de, es decir, donde indica que se verifican todas las asignaciones a los escalares y las variables de subrango. –

+0

Probablemente sería un error de desbordamiento si el tipo de datos fuera entero –

+0

@DavidHeffernan Si el cálculo se realiza en tipos 'Entero ', seguro, pero' i: = i + Int64 (1); '* debería * (no probado) provocar un error de rango cuando 'i' es un' Entero' con un valor de 'MaxInt'. – hvd

Cuestiones relacionadas