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.