PDA

Ver la versión completa : Structs e índices en Bennu



Segata Sanshiro
22/09/2009, 23:41
He estado notando un comportamiento un poco raro en un juego que estoy programando y no consigo encontrar el punto en el que falla. Ya por adelantado, disculpas si esto se ha tratado antes (sobre todo en el foro de Bennu) :D

Por un lado, ¿salta un error al acceder a datos de un struct que no existen? Por ejemplo, si tengo:


struct mapa[3][10][3];
int num1;
int num2;
end

e intento acceder a mapa[10][2][10].num1, efectivamente el compilador detecta un error "Index out of range". Sin embargo, si creamos una variable int i = 10, el compilador no puede detectar que habrá un error, y ya en tiempo de ejecución, si accedo a mapa[2][i].num1, [I]el intérprete tampoco da error, que me parece lo grave. En mi caso, ese acceso en teoría no válido solía devolver el mismo número casi siempre (82405 o algo así). ¿Es un bug? ¿Era conocido ya?

Y lo que me está volviendo loco :D Tengo otro struct:

struct lista[9];
int var1, var2;
end = 0,0,
14, 2,
13, 8,
// ...
2,14; // Valores de ejemplo

En ejecución, compruebo que no me he equivocado al meter los valores después del "end = ...". Los valores de ese struct deberían ser constantes. En ningún momento hago nada como lista[i].var1 = algo, ni lista[i].var1++, ni nada que intente cambiar los valores de lista y sus variables. Sin embargo, en cierto punto durante la ejecución (que no consigo aislar), algunos valores se ponen a cero. En concreto, sería por ejemplo que lista[1].var2 pasa de repente de valer 2 a valer 0 y que lista[3].var2 pasa a valer 0 también.

Si añado una tercera variable dentro del struct (var3 por ejemplo) y cambio la asignación de valores después del end a algo así:

struct lista[9];
int var1, var2, var3;
end = 0,0,0,
14, 2,0,
13, 8,0,
// ...
2,14,0; // Valores de ejemplo

sigue ocurriendo lo mismo, pero ahora son otros los valores que se ponen a cero, por ejemplo lista[1].var2 y lista[2].var2 (en vez de lista[3].var2). No sé dónde puede estar el problema. Sé que el problema deja de ocurrir si elimino cierta llamada a un proceso, pero no comprendo por qué. Esa llamada pasa varios parámetros al nuevo proceso, que lee de otra estructura (llamémosla lista2), y éste nuevo proceso nunca accede para nada a "lista" y sus variables. Y sin embargo, eliminando la llamada, deja de ocurrir el problema de "valores que cambian sin razón aparente". ¿Alguna idea de por dónde seguir buscando?

Muchas gracias a todos los que hayan llegado hasta aquí, si es que hay alguien, y a splinter por su magnífico port de Bennu :D

SplinterGU
22/09/2009, 23:57
hola, el primero no puede ser considerado un error del motor, esos controles se deben hacer por codigo.

con respecto al segundo, necesitaria ver mas del codigo que te da problema... un codigo que se pueda probar (completo) seria de gran ayuda.

Gracias a vos por usar bennu.

Drumpi
23/09/2009, 01:55
Hombre, ten en cuenta que el compilador se da cuenta de que 10 es una constante fuera del rango de valores del array, pero no sabe por qué valores va a pasar 'i', o si antes de buscar en el array se convierte de 10 a 9, las variables no son predecibles, y en ese caso, como en C, es cuestion del programador no salirse.
El único control que tienes es cuando lees fuera de la memoria del programa, que te salta un "segmentation fault" en cualquier UNIX, o la ventana de "se ha producido un error grave en la intrucción tal de tal (chorro de valores hexadecimales)" en según qué versiones de windows (si, algun windows se lo traga mientras no toques memoria del sistema).

En el segundo problema hay un error muy comun:
Cuando declaras
struct tal [9]
indicas que tienes 9 estructuras, pero ojo, van numeradas del 0 al 8. ¿Es eso? Si no, hay algun puntero despendolado por otro sitio (llámale puntero, llámale variable fuera de rango).

Suerte.

SplinterGU
23/09/2009, 04:44
[9] son 10, del 0 al 9 inclusive

GameMaster
23/09/2009, 10:32
Pues por lo que veo los problemas que estoy teniendo tambien provienen de estructuras (adaptación de código fuente para DIV en el que funcionaba bien).

Segata Sanshiro
23/09/2009, 12:56
Hombre, ten en cuenta que el compilador se da cuenta de que 10 es una constante fuera del rango de valores del array, pero no sabe por qué valores va a pasar 'i', o si antes de buscar en el array se convierte de 10 a 9, las variables no son predecibles, y en ese caso, como en C, es cuestion del programador no salirse.

Claro, es imposible que el compilador se dé cuenta, pero en tiempo de ejecución sí se puede detectar y quizás vendría bien lanzar un error. Pero vamos, que poniendo cuidado no hay problema.


En el segundo problema hay un error muy comun:
Cuando declaras
struct tal [9]
indicas que tienes 9 estructuras, pero ojo, van numeradas del 0 al 8. ¿Es eso? Si no, hay algun puntero despendolado por otro sitio (llámale puntero, llámale variable fuera de rango).

Como dice Splinter, es de 0 a 9, curiosamente creo que DIV y derivados son los pocos lenguajes en los que es así.

Estoy intentando hacer una versión simplificada en la que ocurra el problema. He aislado un trozo de código que dependiendo de si está comentado entre /*y */, provoca el error o no. Es un switch ... case ... bastante sencillo, que accede a una tercera estructura (no a la que se modifica de repente). A ver si puedo subir el .prg. Gracias por el interés.

juanvvc
23/09/2009, 13:12
Cuando pones mapa[i][2][10].num1 con i=10 estás accediendo fuera del rango, y según el lenguaje saltará error (Java, Python) o no (C, C++). No sé qué debería hacer Bennu, lo siento, pero parece que no salta error y eso en principio no es malo, es simplemente una caracterísitca del lenguaje...

...que puede tener algo que ver con el siguiente error. Si haces mapa[i][2][10].num1=5 con i fuera del rango, estás escribiendo sobre otra posición de memoria, a saber cuál, y puede que sea precisamente dentro de esa estructura que cambia misteriosamente :)

GameMaster
23/09/2009, 13:16
Como dice Splinter, es de 0 a 9, curiosamente creo que DIV y derivados son los pocos lenguajes en los que es así.



Que va, en los demás es igual por lo menos en VB o C#

PharaOnyx
23/09/2009, 13:18
Que va, en los demás es igual por lo menos en VB o C#
En C# se sigue la convención estándar: int[100] son 100 posiciones, de la 0 a la 99

Saludos, Alex

GameMaster
23/09/2009, 13:29
Tienes razón perdona ;)

Segata Sanshiro
23/09/2009, 13:59
...que puede tener algo que ver con el siguiente error. Si haces mapa[i][2][10].num1=5 con i fuera del rango, estás escribiendo sobre otra posición de memoria, a saber cuál, y puede que sea precisamente dentro de esa estructura que cambia misteriosamente :)

Creo que vas a haber dado en el clavo :D En cierta parte escribo en otra estructura, probablemente fuera de rango, y eso cambia los valores de la primera. De hecho si en vez de poner "= 0" pongo "= 5", los valores efectivamente cambian a 5. La madre del cordero...

Drumpi
23/09/2009, 18:11
Yo ya me hago un lio con los indices de los arrays, en unos lenguajes es de una forma, en otros de otra... voy a tener que consultar el debug a partir de ahora.

De todas formas, el error es lo que decíamos desde el principio: un puntero despendolado.
Probablemente el intérprete podría detectar ese fallo, pero eso haría que el acceso a memoria fuese más lento de lo que ya es, por eso hay que tener tanto cuidado al programar. Y con los punteros este problema se multiplica por dos :D Pero con cuidado no pasa nada.
Bisturí.

SplinterGU
24/09/2009, 02:38
claro, si te vas de los limites pisas memoria... eso es seguro...

el hecho de no chequear esto es runtime es por cuestiones de velocidad... la idea es que las variables que uses solo puedan dar valores en el rango correcto... tampoco es mejor que chequees el limite antes de usarlo, sino seria mas optimo hacerlo en el interprete... por eso lo mejores que las variables ya se manejen en ese rango...