Foros - Stratos

Programadores => General Programadores => Mensaje iniciado por: nsL en 15 de Abril de 2005, 06:27:51 PM

Título: Problemas Con Vector.
Publicado por: nsL en 15 de Abril de 2005, 06:27:51 PM
 Jelow!

Os pongo un poco en antecedentes (brevemente):
Tenia y tengo una clase sprite que puede almacenar varios frames, para animaciones y tal, pero antes para almacenarlos usaba listas enlazadas, hasta q empece a tener problemas de memoria (al añadir cosa de 9 frames (surfaces) me petaba el asunto) asi q decidir cambiar a arrays dinamicos.
Tenia en mente hacer los arrays con calloc pero era un poco pestilente, asi q vi el template vector, que parece q suplia mis necesidades bien.

Esta misma tarde rehago todo el codigo para su uso con vector. Aqui os pego lo relevante al problema que tengo:


struct listaFram
{
 SDL_Surface *frame;
 bool *frmask;
};

vector<listaFram> frameList;

Esto es el "nodo" que usaba antes para las listas enlazadas y ahora para los elementos del array q me cree vector. Como veis creo un vector con 0 elementos.


void CSprite::addframe(char *Path)
{
listaFram *Aux = (listaFram *)malloc(sizeof(listaFram));
frameList.push_back(*Aux);
frameList[++total].frame = IMG_Load(Path);
}


Dejando al margen si compruebo si carga bien o mal el archivo, esta parte funciona bien. Pero solo para 1 frame, ahi esta mi problema. Si intento hacer otro addframe sobre el mismo sprite me salta el parachute famoso del SDL. Es la primera vez q uso vector y en mi libro de C++ tampoco se estira mucho el tio pa explicarlo, asi q puede ser q me olvide algo.

si sabeis q es os agradezco inmensamente la ayuda.

Saludos!  B)

PD: ya que estamos y para no abrir otro post.
Es muy descabellado gastar 13000 bytes por frame en una mascara? solo serian 13 kb por un frame de un boton. Para que os hagais una idea es una variable bool por pixel. 13000 variables bool suena mucho y a mi me parece exagerao quizas, pero frente a la ram tan grande, 13 kbs es insignificante.
Lo digo porq al añadir mascaras a los frames, si añado 2 mascaras o asi ya me peta el programa, supongo q sera porq no tiene memoria. Q pensais?
Título: Problemas Con Vector.
Publicado por: samsaga2 en 15 de Abril de 2005, 07:50:05 PM
 Una pista... el tipo del vector y de la variable que quieres agregar son distintos. Hasta aqui puedo leer.
Título: Problemas Con Vector.
Publicado por: Sacrifai en 15 de Abril de 2005, 08:02:20 PM
Cita de: "samsaga2"Una pista... el tipo del vector y de la variable que quieres agregar son distintos. Hasta aqui puedo leer.
Yo no veo eso  :huh: . Por cierto, me gustaría saber que tipo de error es ese "parachute" XDD y así poder ayudarte.


PD: Yo no reservaría memoria por cada frame que cargas. Haz que cada XX frames te reseve memoria para esos XX frames. El vector lo que hace es multiplicar por dos cuando se llega a su límite(por lo menos antes, no se si ahora harán eso) lo cual creo que es un desperdicio de memoria.
Título: Problemas Con Vector.
Publicado por: Warchief en 15 de Abril de 2005, 08:22:24 PM
 
void CSprite::addframe(char *Path)
{
listaFram *Aux = (listaFram *)malloc(sizeof(listaFram));
frameList.push_back(*Aux);
frameList[++total].frame = IMG_Load(Path);
}


"total" empieza en -1?
Título: Problemas Con Vector.
Publicado por: nsL en 15 de Abril de 2005, 08:56:37 PM
 
Citar
Fatal signal: Segmentation Fault (SDL Parachute Deployed)

Ese es el error, suele darme cuando referencias a una superficie pero q realmente no existe, ya sea porq no se pudo cargar u otro motivo. Aunq si te digo la verdad es el unico error q me da SDL, siempre el parachute :P

Citar
"total" empieza en -1?

Empieza en 0, y asigna a partir del 1. Es decir, frame 1, 2 ,3. Por eso primero incremento, pa posicionarlo en 1 para el primer frame y segun añada q lo meta en el siguiente hueco.

No entendi bien eso de que multiplica por 2, si puedes explica un poco mas plz ;)

Gracias a todos por la ayuda, a ver si consigo solventar esto.

Saludos!  B)  
Título: Problemas Con Vector.
Publicado por: Sacrifai en 15 de Abril de 2005, 09:23:40 PM
 
Cita de: "nsL"No entendi bien eso de que multiplica por 2, si puedes explica un poco mas plz ;)
Veamos, cuando creas un vector tienes cierta memoria reservada para lo que contendrá, es decir, inicialmente tendrá un capacidad de n elementos ( creo que son 32, pero no me hagas mucho caso ) y al llenar esos n elementos con información te multiplica la capacidad total por 2. Esto puede ser una putada, imaginate si tienes cientos de elementos, puede que estes usando doble de memoria de la que quieres usar. Si usas 33 elementos, el vector te hará espacio para 64 con lo cual tienes 31 desaprobechados. Yo lo veo mas rentable aumentar cada 32 otros 32.

Respecto al problema, ¿porque no creas la estructura y le inicias todos los miembros y DESPUES la insertas en el vector?
Título: Problemas Con Vector.
Publicado por: nsL en 15 de Abril de 2005, 09:37:35 PM
 Es que en mi libro dice que si lo pones asi inicialmente esta vacio el vector y segun haces push agregas.
para hacerlo con un tamaño era algo asi: vector caca(32) como dices tu. igual es eso que dices qu antes era distinto y empezaba con un minimo de 32, eso ya no se :P

Respecto a lo de inicializar primero los parametros y luego agregar ya lo probe:


void CSprite::addframe(char *Path)
{
listaFram *Aux = (listaFram *)malloc(sizeof(listaFram));
frameList[++total].frame = IMG_Load(Path);
frameList.push_back(*Aux);
}


y era como lo tenia en un principio, pero asi no me mostraba el sprite. Fue cambiar el orden y empezar a verse el sprite. La verdad q no se donde puede estar el error :S de todas formas gracias por el interes ;)

Saludos!  B)  
Título: Problemas Con Vector.
Publicado por: Warchief en 15 de Abril de 2005, 10:02:54 PM
Cita de: "nsL"
Citar
"total" empieza en -1?

Empieza en 0, y asigna a partir del 1. Es decir, frame 1, 2 ,3. Por eso primero incremento, pa posicionarlo en 1 para el primer frame y segun añada q lo meta en el siguiente hueco.
A eso me refería. Si haces:

main() {
...
miCSprite->add(sprite1);
...
}

No debería hacer:

frameList.push_back(*Aux);
frameList[0].frame = IMG_Load(Path);

?


En cualquier caso:

void CSprite::addframe(char *Path)
{
listaFram *Aux = (listaFram *)malloc(sizeof(listaFram));
frameList[++total].frame = IMG_Load(Path);
frameList.push_back(*Aux);
}


será


void CSprite::addframe(char *Path)
{
listaFram *Aux = (listaFram *)malloc(sizeof(listaFram));
Aux->frame = IMG_Load(Path);
frameList.push_back(*Aux);
}


No?
Título: Problemas Con Vector.
Publicado por: nsL en 15 de Abril de 2005, 10:09:12 PM
 si weno, el ultimo trozo q pusiste es como lo tenia, es que le di la vuelta pensando q era como lo tenia antes pero me equivoque.

respecto a los index del vector, sea cual sea el comienzo, ya sea 0 o 1,  no deberia dar error al cargar otro frame. en todo caso daria error al referenciarlo luego que te equivoques de frame...

de todas formas voy a probar a meter el primer frame en 0 y luego 1, 2, 3 y en 3 minutos edito y te cuento a ver..

PD: si lo pongo pa qu el primero lo meta en 0 no sale ni 1 frame :P
na este es el cuento de nunca acabar :P

Gracias de todas formas ;)
Título: Problemas Con Vector.
Publicado por: Warchief en 15 de Abril de 2005, 10:49:14 PM
 Con el 0 me refería al caso de sprite1; quiero decir usar postincremento en lugar de preincremento.


Volvamos a:
void CSprite::addframe(char *Path)
{
listaFram *Aux = (listaFram *)malloc(sizeof(listaFram));
Aux->frame = IMG_Load(Path);
frameList.push_back(*Aux);
}


despues de addframe puedes acceder a miCSprite->frame bien? (IMG_Load devuelve puntero válido con memoria?, igual falla la carga).
Título: Problemas Con Vector.
Publicado por: nsL en 16 de Abril de 2005, 12:22:39 AM
 No, si lo pongo asi (en ese orden) como te dije no me carga bien (extraño la verdad), sin embargo si primero meto el Aux en el vector y luego relleno los campos si que va. Eso si, solo va el primer frame, los consecutivos da el puto parachute q me esta calentando a mi ya.

ya probe todas las combinaciones posibles respecto a preincremento, postincremento, poner total a 0 ,1 , asignar yo el array con 1 , 0 en vez de con total y nada de nada. Pero lo q me fastidia del tema es que seguro que es alguna parida del tipo for (i = 1; i==i ; i++) o similares, q me suelen tocar el alma cada poko.

He subido todo el codigo fuente a una web por si le quereis echar un ojo, no hace falta ni que compileis, es mirar por encima a ver si veis algo extraño, si quereis o teneis tiempo. sino da igual, si de todas formas poco me entero yo siendo mi codigo, vosotros tendreis q ver para q vale cada cosa y es mas tediosos, pero weno, ahi va:

Na, ahora se me cuelga el pc y no puedo subir el archivo al servidor, y el que subo esta corrupto. Ahora que, revienta el pc y la metralla me mata? porq ya a este paso...

http://usuarios.lycos.es/rage182/sdlbeg.rar
ó http://usuarios.lycos.es/rage182/sdlbeg.zip

a ver si conseguis bajarlo y no esta corrupto

Saludos!
Título: Problemas Con Vector.
Publicado por: Sacrifai en 16 de Abril de 2005, 12:45:12 AM
 ¿Que versión de SDL usas?
Título: Problemas Con Vector.
Publicado por: nsL en 16 de Abril de 2005, 12:55:42 AM
 1.2.8, pero vamos, problema de SDL no es, porq hasta ahora con listas enlazadas conseguia tener varios frames (surfaces) por sprite, pero fue cambiar a vector y algo hago mal que no rula el tema.

ire pa la cama y mañana lo cogere con mas calma, aunq la verdad q como no consiga solucionarlo no se que narices voy a hacer.en fin... tamañana  :D

Título: Problemas Con Vector.
Publicado por: samsaga2 en 16 de Abril de 2005, 09:40:13 AM
 frameList es del tipo listaFram y tu estas haciendo push_back de variables del tipo *listaFram. Lo que quiere decir penchada al canto. Lo que me sorprende es que el compilador no se queje.
Título: Problemas Con Vector.
Publicado por: Warchief en 16 de Abril de 2005, 10:37:03 AM
 
Cita de: "samsaga2"frameList es del tipo listaFram y tu estas haciendo push_back de variables del tipo *listaFram. Lo que quiere decir penchada al canto. Lo que me sorprende es que el compilador no se queje.
El vector es de , pero Aux es , por eso hace *Aux al push.



@nsL

1) Lo que se me ocurre es que como es mem dinámica no situe los elementos del vector en direcciones continuas de memoria. Prueba a usar frameList.at(i) en vez de frameList.

2) Por ejemplo en el codigo del destructor de CSprite:

int i = 1;

while (i != total+1)
{
 SDL_FreeSurface(frameList[i].frame);
 free(frameList[i].frmask);
 i++;
}

Sigo pensando que sería desde 0; en el caso de std::vector::at también:

int i = 0;

while (0 != total)
{
 SDL_FreeSurface(frameList.at(i).frame);
 free(frameList.at(i).frmask);
               // no falta liberar la memoria del frameList.at(i) ? viene de un malloc
            i++;
}


(Es que no tengo sdl pa compilar).
Título: Problemas Con Vector.
Publicado por: nsL en 16 de Abril de 2005, 04:31:13 PM
 Tienes razon, se me estaba olvidando liberar la memoria del vector, solo liberaba su contenido. :P

Citar
1) Lo que se me ocurre es que como es mem dinámica no situe los elementos del vector en direcciones continuas de memoria. Prueba a usar frameList.at(i) en vez de frameList.

Eso seria para referenciar a un frame, pero es qu a mi el error me da nada mas cargar el segundo, no al acceder a el :(

si hago esto por ejemplo:

void CSprite::addframe(char *Path)
{
listaFram *Aux = (listaFram *)malloc(sizeof(listaFram));
frameList.push_back(*Aux);
               printf("%d",frameList.size());
frameList[++total].frame = IMG_Load(Path);
}


en el archivo de salida stdout q se crea con SDL se escribe 1112. los 3 primeros 1 son referentes a el fondo, puntero y el primer frame del boton, y el 2 es cuando cargo el 2º frame del sprite del boton, con lo cual si agrega bien al vector, lo que pasa que:

frameList[++total].frame = IMG_Load(Path);

no rula, no se si por esa sentencia o porque se peta antes. Y el archivo si esta, de echo probe a cargar primero el segundo frame (el que nunca carga) y en segundo lugar el frame que iba bien, y me pasa lo mismo, el que cargue en 2º lugar es el que no va.

Ya me canse de vector :P si sabes/eis alguna otra forma de almacenarlos dinamicamente os lo agradezco.
Aunq ahora q lo pienso podria hacerlo estatico pues sere yo quien los cargue en cada momento y se cuantos frames son realmente, aunq yo lo hacia dinamico por abstraerme de andar modificando los indices cada vez, pero en fin...

Gracias una vez mas por la ayuda y Saludos!  B)

Título: Problemas Con Vector.
Publicado por: Warchief en 16 de Abril de 2005, 04:38:36 PM
 Lista dinámica enlaza. Pon un puntero dentro de las estructura que sea a una estructura del mismo tipo. En el objeto guarda solo el puntero al primero (recomendablemente al ultimo también) de esa estructura, y cada uno que apunte al siguiente. Cuando uno apunta a NULL es el último.  
Título: Problemas Con Vector.
Publicado por: nsL en 16 de Abril de 2005, 04:44:18 PM
 asi es como lo tenia antes :P

y iba bien la verdad, no se pa q meti las narices con vector....
Lo q pasa es que me daban problemas de memoria, q solo me cargaban pocos frames por culpa de las maskaras , q yo creo q son excesivamente grandes...

Y como no hice copia de seguridad de los metodos con listas enlazadas me voy a cortar las venas :P

Saludos!  (ole)  
Título: Problemas Con Vector.
Publicado por: ProD en 17 de Abril de 2005, 12:03:10 PM
 Buenas.. a mi se me ocurre esto:

[CODE]

void CSprite::addframe(char *Path)
{
 listaFram newFrame = {NULL, NULL};

 // Cargamos el frame
 newFrame.frame = IMG_Load(Path);
 assert(newFrame.frame != NULL);

 // Lo guardamos
 frameList.push_back(newFrame);
}

Prueba esto a ver si rula... aunque te cargue los frames del 0 en adelante. Si funciona luego
puedes adaptarlo para que cargue a partir del 1. Saludos.
Título: Problemas Con Vector.
Publicado por: Sacrifai en 17 de Abril de 2005, 12:45:02 PM
 ¿Olle y porque no te montas tu arreglo dinamico?Seguro que así funciona.
Título: Problemas Con Vector.
Publicado por: nsL en 17 de Abril de 2005, 02:54:00 PM
 ProD esta tarde pruebo eso.
Por cierto, la assert me la tengo q crear o viene con alguna libreria?, es que en mi libro se la crea el tio.

Sacrifai, a que te rfieres con arreglo dinamico :P

Gracias y Saludos!  B)  
Título: Problemas Con Vector.
Publicado por: nsL en 17 de Abril de 2005, 03:13:49 PM
 ya lo probe y no va  (ole)

Me pasa como siempre, si relleno el campo frame antes de hacer el push_back no se carga el frame, tengo q ponerlo asi pa q se vea:


listaFram newFrame = {NULL, NULL};
frameList.push_back(newFrame);
frameList[++total].frame = IMG_Load(Path);


Sino na de na, y si lo pongo asi sigue sin cargarme 2 frames.
A mi ya me hace gracia la cosa, porq es algo tan raro q ni vosotros q teneis mas experiencia entendeis, porq deberia ir bien... en fin Salu2

Por cierto, el assert q se supone q dice el tipo de error o que? porq lo ponga o no me pasa lo mismo y no veo mensaje alguno  :blink:  
Título: Problemas Con Vector.
Publicado por: samsaga2 en 17 de Abril de 2005, 03:22:07 PM
 Me he leido ahora el problema bien (no como antes con la chorrada que dije que no funciona). El error que te esta dando es de corrupcion de memoria, es decir, el programa intenta acceder a una zona de memoria que no le toca (por explicarlo de alguna forma). Eso quiere decir que el error no debe estar necesariamente en la linia en la que peta si no que puede deberse a alguna gestion erronea de memoria que hagas con anterioridad. Lo que puedes hacer es usar el debugger y aplicaciones como Valgrid para intentar encontrar donde esta realmente el fallo.
Título: Problemas Con Vector.
Publicado por: Sacrifai en 17 de Abril de 2005, 03:28:44 PM
 Pues que te montes un vector propio usando un array dinamico(punteros, vamos). Cada vez que reescales el array llamas a la función que tengas para asignar la memoria.
Título: Problemas Con Vector.
Publicado por: Warchief en 17 de Abril de 2005, 03:47:55 PM
Cita de: "nsL"Por cierto, el assert q se supone q dice el tipo de error o que? porq lo ponga o no me pasa lo mismo y no veo mensaje alguno  :blink:
http://www.opengroup.org/onlinepubs/007908...h/assert.h.html


#include <assert.h>

main() {
 bool miCondicion = false;
 assert(miCondicion);
}


Assert:
- Si la condición es verdad no pasa nada
- Si la condición es mentira saca un error irrecuperable diciendo qué condición falla.
(es bueno para índices erróneos, punteros nulos, etc.)

En el ejemplo de código saldría un mensaje diciendo que ha fallado el programa porque no se cumple "miCondicion".