Autor Tema: Detectar desbordamiento de variables  (Leído 5235 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Gonzalo_BlackHawk

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 519
Detectar desbordamiento de variables
« en: 13 de Diciembre de 2007, 17:21:37 »
Hola a todos, ¿Existe alguna forma de detectar cuando una variable toma un valor que esta fuera de su rango? En CCS, me ha sorprendido poder por ejemplo:

long numero;

numero = 124155616;
printf("%lu", numero);

Sin obtener ningun tipo de error del compilador. En tiempo de ejecucion, obviamente lo que se imprime con la funcion printf no es mas que un numero que en nada coincide al original.
Tengo que convertir una cadena de texto a un numero y cuando uno escribe un numero mayor que 65536, el resultado obtenido es aleatorio y no puedo detectar el desbordamiento. ¿Alguna ayuda?? Estoy usando el CCS version 4.057, una de las mas recientes.

GONZA
"Siempre piensa si el jugo vale la exprimida..."

"La muerte esta tan segura de vencer que nos da toda una vida de ventaja."

Desconectado Gonzalo_BlackHawk

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 519
Re: Detectar desbordamiento de variables
« Respuesta #1 en: 13 de Diciembre de 2007, 18:28:57 »
JCC40, nadie critica al CCS ni al lenguaje C, que tantas facilidades nos ha dado al programar los PIC, estoy preguntando si nadie ha desarrollado una rutina general, si es que existe, para poder detectar desbordamiento de variables. En mi programa, el usuario ingresa mediante el UART una cadena de texto que se convierte a un numero de 16 bits, por lo tanto saber que va a escribir el usuario es ciertamente impredecible. Las comparaciones con los operadores de desigualdad estandares (< o >) no sirven cuando las variables estan fuera de su rango y no se me ocurren muchas ideas viables para realizar la comparación, porque cuando desborda la variable inmediatamente toma un valor numerico válido, por un proceso que no estoy en condiciones de comprender. Supongo que hilando mas fino en los registros de la memoria del PIC tal vez se pueda hacer algo, no lo se, estoy divagando.
Espero alguna persona caritativa y con mas experiencia que yo en C, que me pueda decir como solucionar mi problema. Nos vemos.

GONZA.
"Siempre piensa si el jugo vale la exprimida..."

"La muerte esta tan segura de vencer que nos da toda una vida de ventaja."

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Detectar desbordamiento de variables
« Respuesta #2 en: 13 de Diciembre de 2007, 19:19:26 »
A nivel assembler, existen banderas especiales que indican si un registro se ha desbordado.

Sin tener que meterte en eso, ¿por que no lo planteas asi?

Una vez que el usuario ha ingresado el numero, anda leyendolo de der a izq. es decir, comenzas por las unidades.

Como pensas almacenarlo en un numero de 16 bits, podes tranquilamente guardar unidades,decenas,centenas y unidades de mil ingresadas por el usuario en una variable temporal(que recomiendo sea de 32 bits).

Luego, podes ir sumando el proximo digito(decenas de mil) a la variable temporal, y comparar si excede el valor 65535(si trabajas sin signo). Si no lo excede, lo sumas a lo ya previamente almacenado.

Es lo que se me ocurre en este instante.

Saludos.
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado huichoman

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 186
    • Pequeñas piezas para grandes proyectos.
Re: Detectar desbordamiento de variables
« Respuesta #3 en: 13 de Diciembre de 2007, 20:56:25 »
Hola. Viendo el problema. Hice un pequeño programa en Devc. Es fácil pasarlo al compilador de ccs.
Esta es la forma en que lo haría.

Suponiendo que el número que el usuario ingresa no debe de superar el valor de 65535 y suponiendo que dicho valor lo obtienes incialmente como una cadena de caracteres. Espero que te de una idea de como solucionar el problema. Partiendo del código que te anexo, puedes realizar las modificaciones pertinentes para adaptarlo a tus necesidades. Cualquier duda me dices, y veo en quepuedo ayudarte. Saludos. 

Código: [Seleccionar]

    char num[10];
    char aux1[4],aux2[4];
    int x,n1,n2,n3;
   
    {
     printf("Ingresa el numero: ");   //Pedimos al usuario el numero
     scanf("%s",&num);                  //y lo guardamos en la variable num
     
        for(x=0;x<=2;x++)             //Guardamos los tres primeros caracteres
        aux1[x]=num[x];                //en la variable  aux1
       
    for(x=3;x<=4;x++)               //Guardamos los tres primeros caracteres
        aux2[x-3]=num[x];           //en la variable aux2
   
        n1=atoi(aux1);                 //Convertimos aux1 en un entero y se guarda en n1
        n2=atoi(aux2);                 //Convertimos aux2 en un entero y se guarda en n2
       
     if ((n1<=655)&&(n2<=35))   //Preguntamos lo pertinente, si cumple podemos tranquilamente
        n3=atoi(num);                 //convertir num en un entero y guardarlo en n3.
        else                               
        printf("\n DESBORDAMIENTO\n\n");  //Si no cumple mandamos a volar al usuario.
       
}

Desconectado Gonzalo_BlackHawk

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 519
Re: Detectar desbordamiento de variables
« Respuesta #4 en: 13 de Diciembre de 2007, 22:01:04 »
Bueno, revisando un poco los conceptos sobre el funcionamiento de los registros del microcontrolador, me he dado cuenta que el resultado que se obtiene en una variable desbordada no es ni aleatorio ni al azar (como yo pensaba), sino simplemente el valor que se ha intentado grabar menos el rango de la variable cuantas veces sea posible (por ejemplo para una variable de 8 bits o un rango de 255, al intentar grabar la variable 265, obtendremos como resultado 10, o sea 265 - 255). Esa es una duda que tenia pendiente y la comparto con ustedes, aunque de seguro se han dado cuenta mas rapido que yo. :? .

Con respecto a sus aportes, BrunoF, tu respuesta me parece una muy buena idea, pero en mi constante afan de exprimir al maximo la memoria del PIC, evito utilizar variables de 32 bits, pero claro que la tendre en cuenta, es una solucion muy simple y eficaz.
La respuesta de huichoman es brillante, aunque un poco mas elaborada que la de BrunoF, pero lo cual no le quita merito. ADemas puedo comprobar si desborda el valor antes de convertirla a una variable numerica, lo que me facilita mucho el trabajo.
Muchas gracias muchachos, voy a probarlos en mi programa y luego les traigo noticias acerca de como me quedo el codigo.

Saludos.
"Siempre piensa si el jugo vale la exprimida..."

"La muerte esta tan segura de vencer que nos da toda una vida de ventaja."

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: Detectar desbordamiento de variables
« Respuesta #5 en: 14 de Diciembre de 2007, 04:22:47 »
Efectivamente Gonzalo, una variable que desborda no es más que una variable que se pone a 0 y sigue acumulando valores.

Desconectado maunix

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 4751
    • Mi Sitio Web Personal
Re: Detectar desbordamiento de variables
« Respuesta #6 en: 14 de Diciembre de 2007, 09:10:03 »
Bueno, revisando un poco los conceptos sobre el funcionamiento de los registros del microcontrolador, me he dado cuenta que el resultado que se obtiene en una variable desbordada no es ni aleatorio ni al azar (como yo pensaba), sino simplemente el valor que se ha intentado grabar menos el rango de la variable cuantas veces sea posible (por ejemplo para una variable de 8 bits o un rango de 255, al intentar grabar la variable 265, obtendremos como resultado 10, o sea 265 - 255). Esa es una duda que tenia pendiente y la comparto con ustedes, aunque de seguro se han dado cuenta mas rapido que yo. :? .
Esa es la idea del foro, compartir no solo conocimiento sino también dudas e inquietudes.  Lo que te ha pasado es simplemente lo que nos pasa a todos la 1ra vez que nos topamos con el C y su "casteo bajo o nulo" lo que lo hace muy potente y eficiente a la hora de compilarse en lenguaje ensamblador pero 'peligroso' a la hora de desarrollar si no se tiene el cuidado apropiado.

Lo mismo te pasaría si declaras una variable de 1 byte con signo y la haces igual a 128. :)  , Ese sería otro desbordamiento también.  Tu piensas que tienes guardado un hermoso 128 pero en realidad es -1 jeje.  El C no chillará en nada.


Con respecto a sus aportes, BrunoF, tu respuesta me parece una muy buena idea, pero en mi constante afan de exprimir al maximo la memoria del PIC, evito utilizar variables de 32 bits, pero claro que la tendre en cuenta, es una solucion muy simple y eficaz.


Es que tal sea la única forma.  ¿Cómo hacer sino?  Tenes que tener un espacio en memoria mayor al que quieres comparar, sino estas en problemas.  Ahora si el ingreso es por teclado o algun otro medio e interviene un usuario, sería un 'uso temporal de la memoria excesiva' tampoco es para volverse loco.  Si usas un compilador de C y usas variables locales, estas se alojarán en el stack del compilador con lo cual al salir de la rutina dejarán de ocupar lugar.

Siendo más estricto si quieres realmente tener control de lo que ingresará el usuario no debieras usar el SCANF ni ninguna función estándar del c, sino hacer tu mismo tu propia rutina de lectura y validación.  Validación es 'aceptar realmente lo que hace falta, ni mas ni menos'.  Por ejemplo si es ingresado por teclado y sería un número con decimales, no debieras permitir que el usuario ingrese dos veces la "," por citar solo un ejemplo.   :mrgreen: :mrgreen:

- La soberbia de un Einstein es entendible.. la de un salame es intolerable (A.Dolina)
- En teoría no hay diferencia entre la teoría y la práctica. En la práctica... si la hay.
- Lee, Lee, Lee y luego pregunta.(maunix)
- Las que conducen y arrastran al mundo no son las máquinas, sino las ideas (V. Hugo)
- Todos los hombres se parecen por sus palabras; solamente las obras evidencian que no son iguales.(Moliere)
- Todo debería ser hecho tan simple como sea posible pero no mas simple que eso.(A.Einstein)

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Detectar desbordamiento de variables
« Respuesta #7 en: 14 de Diciembre de 2007, 11:00:11 »
Bueno, revisando un poco los conceptos sobre el funcionamiento de los registros del microcontrolador, me he dado cuenta que el resultado que se obtiene en una variable desbordada no es ni aleatorio ni al azar (como yo pensaba), sino simplemente el valor que se ha intentado grabar menos el rango de la variable cuantas veces sea posible (por ejemplo para una variable de 8 bits o un rango de 255, al intentar grabar la variable 265, obtendremos como resultado 10, o sea 265 - 255). Esa es una duda que tenia pendiente y la comparto con ustedes, aunque de seguro se han dado cuenta mas rapido que yo. :? .

El resultado almacenado es:

valor_ingresado % pow(2,nbits)

ejemplo:

Si queres guardar el valor 357 en una variable de 8 bits(1 byte):

357 % pow(2,8) = 357 % 256 = 357 MOD 256 = 101.

Con respecto a sus aportes, BrunoF, tu respuesta me parece una muy buena idea, pero en mi constante afan de exprimir al maximo la memoria del PIC, evito utilizar variables de 32 bits, pero claro que la tendre en cuenta, es una solucion muy simple y eficaz.
La respuesta de huichoman es brillante, aunque un poco mas elaborada que la de BrunoF, pero lo cual no le quita merito. ADemas puedo comprobar si desborda el valor antes de convertirla a una variable numerica, lo que me facilita mucho el trabajo.
Muchas gracias muchachos, voy a probarlos en mi programa y luego les traigo noticias acerca de como me quedo el codigo.

Saludos.

Sólo te hace falta utilizar temporalmente 1 variable de 32 bits! Creo que poder solucionar tu problema  sacrificando temporalmente 4 bytes y un par de Words de Flash de más que genere el compilador por trabajar con 32bits ese trozo de código es un negoción...



Saludos.
« Última modificación: 14 de Diciembre de 2007, 11:04:06 por BrunoF »
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado RICHI777

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1498
Re: Detectar desbordamiento de variables
« Respuesta #8 en: 14 de Diciembre de 2007, 12:49:07 »
Tratando de aportar algo...
El rango de una variable es definido por el usuario, como comento Bruno, para detectar el overflow "logico" deberias extender el rango de la variable en cuestion, si tu rango es 0-255 y almacenas en bytes, pasa temporariamente por un variable word y ahi haces la comparacion, lo mismo se aplica para variables word.
Salu2!

Desconectado jfh900

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3595
Re: Detectar desbordamiento de variables
« Respuesta #9 en: 14 de Diciembre de 2007, 13:23:15 »
Bueno ya te han dado la respuesta, pero yo te la concreto algo más:

Código: [Seleccionar]
int32 valor;

valor=atoi32(cadena);

if (valor>65535)
{
....
<error>
....
}

Un saludo
* Cuando hables, procura que tus palabras sean mejores que el silencio.
* 'Todos somos ignorantes, lo que ocurre es que no todos ignoramos las mismas cosas.' Albert Einstein.
* No hay nada peor que un experto para evitar el progreso en un campo
* "La vida es como una novela. No importa que sea larga, sino que esté bien narrada" Seneca
* La vida no se vive por las veces que respiras, sino por los momentos que dejan sin aliento.
* Dios dijo: ∇·E=ρ/ε0 ; ∇·B=0 ; ∇xE=-dB/dt ; ∇xB= μ0ε0dE/dt..y la luz se hizo..!!..

Desde España Jesús

Desconectado PalitroqueZ

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5474
    • Electrónica Didacta
Re: Detectar desbordamiento de variables
« Respuesta #10 en: 14 de Diciembre de 2007, 17:40:41 »
en el mundo de la programación y cuando va dirigido al público en general, es primordial colocar rutinas de control de errores a los programas que escribimos.


La propiedad privada es la mayor garantía de libertad.
Friedrich August von Hayek

Desconectado Gonzalo_BlackHawk

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 519
Re: Detectar desbordamiento de variables
« Respuesta #11 en: 14 de Diciembre de 2007, 18:00:39 »
Muchas gracias por sus respuestas. He resolvido el problema de una forma bastante obvia pero que paso desapercibida en mi hasta que escuche sus opiniones. Yo poseia una funcion construida por mi(muy similar en sus conceptos a atol, pero modificada a mis necesidades) que permitia convertir strings a variables de 16 bits y que me devolvia un 1 cuando ocurria un error durante la conversión, o un cero si la conversion fue satisfactoria. El problema era que la funcion siempre convertia la cadena en numero sin importar si estaba desbordada o no.
Mi forma de solucionar el problema fue muy simple, volver a convertir ese numero en string con la funcion sprintf y compararla con la recibida por el puerto UART, y si cualquier numero era distinto al original se produce un error y la funcion no retorna nada.
El resultado es una funcion para convertir cadenas a numeros con deteccion de desbordamiento y en la que ademas no necesite utilizar ninguna variable extra para realizarla, yo tan quisquilloso con ese tema.
No se si sera tan rapida o tan eficiente como pasar la variable de 16 bits a una de 32 pero es una solucion elegante a mis problemas en particular y que ademas se puede utilizar con cualquier tipo de variable, hasta de 32 bits. Aqui esta la funcion, bastante descolgada pero su uso es general asi que sirve para cualquier programa. La unica variable global es Cadena, que la tenia disponible y que la uso para operaciones temporales, pero puede reemplazarse por una variable local sin ningun tipo de problema.

Código: [Seleccionar]
short Texto_a_Numero(long *Variable, char *Texto)
{
long Resultado = 0;                                    // Resultado temporal de la conversión.
Int Posicion = 0;                                        // Posición del caracter dentro de la cadena de texto.
Char Caracter;                                          // Caracter que se esta convirtiendo.
int i = 0;

for(i = 0; i<6; i++){    // Borro la variable Cadena, que es global y que la tengo disponible.
         Cadena[i] = '\0';
}

Caracter = Texto[Posicion++];
if (Caracter=='\0'){return 1;};     // Si la cadena es nula la funcion termina y                                       
                                                                 // devuelve el valor 1.

while (Caracter!='\0'){
   if (Caracter >= '0' && Caracter <= '9'){              // Genera un bucle que convierte secuencialmente todos los caracteres de     
         Resultado = 10*Resultado + (Caracter - '0');      // la cadena.
         Caracter = Texto[Posicion++]; // Se pasa al siguiente caracter.
   }
   else{return 1;} // Si el caracter que se esta analizando no es numerico la función retorna el
}                                                                             //valor uno.


sprintf(Cadena,"%lu",Resultado);                               // Convierte el numero a string otra vez.
if (!Comparar_Cadena(Cadena,Texto,strlen(Texto))){ // Comparar_cadena es muy similar a strncmp.
return 1;                             
}      // Si el caracter que se esta analizando no es numerico la función retorna el
                                                                              // valor uno.
*Variable = Resultado;   // La variable definida como parametro almacena el valor convertido.
return(0);                                        // La función retorna el valor cero indicando que no hubo error durante la
                                                                             // conversion.
}

Perdon por la tabulacion del programa, lo pegue bastante mal. Saludos.
"Siempre piensa si el jugo vale la exprimida..."

"La muerte esta tan segura de vencer que nos da toda una vida de ventaja."