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
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.
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.
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
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.
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.
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;
};
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.
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.
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.
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)
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
¿ 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
pon un breakpoint en el case default y cuando llegue mira desde donde esta llegando. Si sabes la procedencia lo sabes todo.