Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Switch "esotérico"

Iniciado por Capiflash, 10 de Abril de 2006, 04:08:37 PM

« anterior - próximo »

Capiflash

 Os cuento , tengo un switch , en donde llamo a una función en cada case . Funcionar funciona , pq llama a las funciones , pero luego siempre ejecuta tambien las instrucciones que hay en la etiqueta default del switch , ¿por qué la ejecuta ??

  void System_call(ExceptionType which)
  {
     int type = machine->ReadRegister(2);
     if (which == SyscallException) {
        switch (type)
        {
           case (SC_Halt):
              cout << "Machine halting.."<<endl;
              interrupt->Halt();
              break;
       
           case (SC_Read):
            //cout << "Llamada a read" << endl;
              readaux();
              break;
       
           case (SC_Write):
            //cout << "Llamada a  write" << endl;
            //int addr= machine->ReadRegister(4);//leemos el registro donde se almacena la direccion de la cadena
              writeaux();//llamamos a una funcion auxiliar para realizar la operacion
              break;
           default:
              printf("Unexpected user mode exception %d %d\n", which, type);}
       ;}
     else {
        assert(FALSE);
     };


Gracias de antemano

zupervaca

 Te recomiendo poner el codigo de esta manera ya que creo que es mucho mas sencillo de leer y verlo de un vistazo:

void System_call(ExceptionType which)
{
   int type = machine->ReadRegister(2);
   if (which == SyscallException)
   {
       switch (type)
       {
       case (SC_Halt):
           cout << "Machine halting.."<<endl;
           interrupt->Halt();
           break;

       case (SC_Read):
           //cout << "Llamada a read" << endl;
           readaux();
           break;

       case (SC_Write):
           //cout << "Llamada a  write" << endl;
           //int addr= machine->ReadRegister(4);//leemos el registro donde se almacena la direccion de la cadena
           writeaux();//llamamos a una funcion auxiliar para realizar la operacion
           break;

       default:
           printf("Unexpected user mode exception %d %d\n", which, type);
       };
   }
   else
   {
       assert(FALSE);
   };
}

Para solucionarlo tal vez deberias de poner un punto de ruptura al inicio de la funcion y otros en cada case y en el default, asi sabras en que momento se cuela, a primera vista veo que todos los case tienen un break con lo que no veo el problema dentro de la funcion, mira a ver si alguna funcion de las que llamas, tienen dentro una llamada a System_call y por eso te sale.

Pablo Zurita

 Fíjate los punto y coma que tenes antes de cerrar el scope del if (which == SyscallException) y el punto y coma que tenes al cerrar el scope del else.

Capiflash

 Pues no , ninguna de las funciones a las que llamo vuelven a llamar a System_Call .
He estado mirando , el switch funciona , sabe diferenciar los casos y ejecutar las funciones pertinentes , pero cuanod termina ejecuta la etiqueta default , me resulta muy extraño

_Grey

 El ";" de los dos "};" sobra, igual que los () en los case, de todas formas no deberia ser eso.... claro que siempre es posible que el compilador tenga algun problema con ello.... :ph34r:

Al margen de eso lo veo correcto, seguro que no llamas a System_call() otra vez!? ni siquiera dentro de las funciones que usas en los cases (Halt(),readaux(),writeaux())!?

Saludos.

Pogacha

 Edit: se me colo un quote a zupervaca ...
Prueba con:

void System_call(ExceptionType which)
{
   static int llamadas = 0;

   printf("Comienzo de la llamada: %d\n", ++llamadas);

   int type = machine->ReadRegister(2);
   if (which == SyscallException)
   {
       switch (type)
       {
       case (SC_Halt):
           printf("SC_Halt en la llamada: %d\n", ++llamadas);
           cout << "Machine halting.."<<endl;
           interrupt->Halt();
           break;

       case (SC_Read):
           printf("SC_Read en la llamada: %d\n", ++llamadas);
           //cout << "Llamada a read" << endl;
           readaux();
           break;

       case (SC_Write):
           printf("SC_Write en la llamada: %d\n", ++llamadas);
           //cout << "Llamada a  write" << endl;
           //int addr= machine->ReadRegister(4);//leemos el registro donde se almacena la direccion de la cadena
           writeaux();//llamamos a una funcion auxiliar para realizar la operacion
           break;

       default:
           printf("Default en la llamada: %d\n", ++llamadas);
           printf("Unexpected user mode exception %d %d\n", which, type);
       };

         printf("Fin del switch la llamada: %d\n", ++llamadas);
   }
   else
   {
       printf("Assert en la llamada: %d\n", ++llamadas);
       assert(FALSE);
   };
    printf("Fin de la llamada: %d\n", ++llamadas);
}

Luego vuelcanos la salida,
cambia el printf por el cout, para evitar el problema de printf vs cout.
Saludos.

Capiflash

 Completo el codigo con las dos funciones implicadas...


  void readaux()
  {
   //cout <<"Escriba..."<<endl;
     int addr= machine->ReadRegister(4);//leemos el registro donde se almacena la direccion destino de la cadena
     char carac;
     scanf("%c",&carac);
     while (true)
     {
        if (carac=='\n')
           break;//se lee hasta el retorno de carro
        if (not machine->WriteMem(addr,1,(int)carac))
        {
           ExceptionHandler(AddressErrorException); //lanzar excepcion, no se pudo escribir
           return; //finalizamos la accion de leer
        }
        addr++;
     
        scanf("%c",&carac);
     }
     addr++;
 
     if(!machine->WriteMem((int)addr,1,(int)'\0'))
        ExceptionHandler(AddressErrorException);
 
  //cout <<"Hemos salio de read sin error de memoria"<<endl;
     return;
  };

  void writeaux()
  {  
     int addr= machine->ReadRegister(4);//leemos el registro donde se almacena la direccion de la cadena
     int value;
 
     while (true)
     {
        if (not machine->ReadMem(addr,1,&value))
        {
           ExceptionHandler(AddressErrorException); //lanzar excepcion, no se pudo leer;
           return; //finalizamos por error de memoria
        }
        addr++;
        if (value=='\0')
           break;
        cout << (char)value;
     }
     return;
 
  };

Jare

 Mientras los breaks estén bien puestos, ell switch solamente entra en una de las etiquetas, o sea que si te está entrando en varias será porque está pasando varias veces por el switch. Es posible que desde las llamadas a read y write se esté generando una llamada de vuelta a System_call()?

Por lo demás, hay cosas de estilo de programacion que me hacen llorar. :)
if (tal)
...
else
 assert(FALSE);
// ------------------------
while (true)
{
 if (carac=='\n')
   break;
...

Por qué no poner lo siguiente?
assert(tal);
...
// ------------------------
while (carac!='\n')
{
...

Ya se que suena a pijadas pero cuando el código es fácil de leer, tambien suele ser más fácil de depurar.

zupervaca

 La funcion "ExceptionHandler" me imagino que genera la clase o estructura excepcion, ¿esta funcion no estara llamando a System_call para saber que tipo de excepcion debe de retornar?

Si no, lo unico que se me ocurre es ver si es un problema de pisar la pila o el codigo con bufers de datos, para ello mete esto "char basura[1024*1024];" al inicio de la funcion System_call, es decir:

void System_call(ExceptionType which)
{
  char basura[1024*1024];
  int type = machine->ReadRegister(2);
  if (which == SyscallException)
  ...

si por algun casual se ha pisa la pila o este codigo, ahora no fallara ya que se pisara el array basura, si te funciona esto no es una solucion, esto solo sirve para saber si es este el problema ;)

Editado: Teoricamente podras asignar un array de un mega ya que es memoria automatica, pero puede que tengas que ponerle menos dependiendo del compilador y sistema operativo.

Pogacha

 
Ok has lo que dije primero, sacale los ++llamadas excepto a la primera que se me colaron y agrega un contador de recursividad.


void System_call(ExceptionType which)
{
   static int llamadas = 0;
   static int recursion = 0;

   recursion++;
   llamadas++;
   printf("Comienzo de la llamada: %d, recursion: %d\n", llamadas, recursion);

   int type = machine->ReadRegister(2);
   if (which == SyscallException)
   {
       switch (type)
       {
       case (SC_Halt):
           printf("SC_Halt en la llamada: %d, recursion %d\n", llamadas, recursion);
           cout << "Machine halting.."<<endl;
           interrupt->Halt();
           break;

       case (SC_Read):
           printf("SC_Read en la llamada: %d, recursion %d\n", llamadas, recursion);
           //cout << "Llamada a read" << endl;
           readaux();
           break;

       case (SC_Write):
           printf("SC_Write en la llamada: %d, recursion %d\n", llamadas, recursion);
           //cout << "Llamada a  write" << endl;
           //int addr= machine->ReadRegister(4);//leemos el registro donde se almacena la direccion de la cadena
           writeaux();//llamamos a una funcion auxiliar para realizar la operacion
           break;

       default:
           printf("Default en la llamada: %d, recursion %d\n", llamadas, recursion);
           printf("Unexpected user mode exception %d %d\n", which, type);
       };

         printf("Fin del switch la llamada: %d, recursion %d\n", llamadas, recursion);
   }
   else
   {
       printf("Assert en la llamada: %d, recursion %d\n", llamadas, recursion);
       assert(FALSE);
   };
    printf("Fin de la llamada: %d, recursion %d\n", llamadas, recursion);
    recursion--;
}


Con esto tienes para debuguear, si hay problemas con los bufferes de cout y printf, cambialos a uno pero no importa, danos el volcado.

Pogacha

Cita de: "zupervaca"La funcion "ExceptionHandler" me imagino que genera la clase o estructura excepcion, ¿esta funcion no estara llamando a System_call para saber que tipo de excepcion debe de retornar?

Si no, lo unico que se me ocurre es ver si es un problema de pisar la pila o el codigo con bufers de datos, para ello mete esto "char basura[1024*1024];" al inicio de la funcion System_call, es decir:

void System_call(ExceptionType which)
{
  char basura[1024*1024];
  int type = machine->ReadRegister(2);
  if (which == SyscallException)
  ...

si por algun casual se ha pisa la pila o este codigo, ahora no fallara ya que se pisara el array basura, si te funciona esto no es una solucion, esto solo sirve para saber si es este el problema ;)

Editado: Teoricamente podras asignar un array de un mega ya que es memoria automatica, pero puede que tengas que ponerle menos dependiendo del compilador y sistema operativo.
Que inteligente solución supervaca, la verdad es que no la tenia.  (ole)  

Capiflash

 Waw , gracias a todos la verdad , no esperaba tantas respuestas :D:D  (ole)  (ole)

Ahora mismo no puedo probar ninguna de las ultimas posibilidades que me habeis dado , puesto que el codigo lo compilo en una maquina remota , y aqui en casa no tengo manera de hacerlo , en cuanto pueda os comento.

Por otra parte , el codigo no es completamente mio , yo tambien tengo mis "peleas" con la forma de programar de alguno de mis compañeros  xDD

Saludos a todos y gracias

fiero

 ¿ y por que poner '};' ?
Eso es como poner '};;;;;;;;;;;'  o sea, que no sirve para nada, aunque tampoco da ningún error.

Lo mejor es seguir los consejos que habeis dado para hacer el código más legible, y descubrir los posibles fallos de un vistazo.

Yo también utilizo llaves en los case, para que quede bien claro, así:

switch(variable)
{
   case 1:
   {
       n=n;
   }break;
   case 2:
   {
       n=n;
   }break;
   default:
   {
       n=n;
   }
}


un saludo
www.videopanoramas.com Videopanoramas 3D player

seryu

 pon un breakpoint en el case default y cuando llegue mira desde donde esta llegando. Si sabes la procedencia lo sabes todo.






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.