Memory Leaks al crear el contexto de video en SDL

Llevo mucho usando esta librería, pero hasta hace poco no me dió por probar a alterar el modo de video en medio de la ejecución (activar pantalla completa, desactivarla, redimensionar ventana, etc...). El resultado era bueno, hasta que se colgaba xD. La cuestión es que me puse a aislar el código y finalmente a pasarle el Valgrind para detectar en que circunstancias hay fugas de memoria, y he llegado a la conclusión de que las fugas me las produce la función SDL_SetVideoMode, ni más ni menos [tomaaa] Vale, quizás lo hago mal xD Por ello quiero una segunda opinión. El código simplificado sería el siguiente:
[...]
int main(int argc,char* argv[]) {
    SDL_Init(SDL_INIT_VIDEO);
    atexit(SDL_Quit);
    SDL_Surface* main = SDL_SetVideMode(320,240,32,SDL_SWSURFACE);
    SDL_QuitSubSystem(SDL_INIT_VIDEO);
    SDL_InitSubSystem(SDL_INIT_VIDEO);
    SDL_Surface* main = SDL_SetVideMode(320,240,32,SDL_SWSURFACE | SDL_FULLSCREEN);
    return 0;
}

Y el resultado del Valgrind es este:
==7620== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 681 from 4)
==7620== malloc/free: in use at exit: 121,112 bytes in 999 blocks.
==7620== malloc/free: 27,027 allocs, 26,028 frees, 5,599,540 bytes allocated.
==7620== For counts of detected errors, rerun with: -v
==7620== searching for pointers to 999 not-freed blocks.
==7620== checked 781,128 bytes.
==7620==
==7620== LEAK SUMMARY:
==7620==    definitely lost: 800 bytes in 24 blocks.
==7620==      possibly lost: 0 bytes in 0 blocks.
==7620==    still reachable: 120,312 bytes in 975 blocks.
==7620==         suppressed: 0 bytes in 0 blocks.


Supongo que el fallo será mio, o del Valgrind, no he encontrado a nadie que se queje de esta última versión de la SDL. A ver si alguien me echa una mano...
Cuando dices la ultima version te refieres a la 1.3?, yo uso la 1.2.X y ningun problema de ese tipo. A simple vista diria que la forma de iniciar la pantalla no es muy correcta, tal vez seria mejor hacer una copia con el createsurface y copiarla cambiando los valores, de hecho asi lo hago yo y ningun problema.


Primero en el main preparo las pantallas
pantalla = SDL_SetVideoMode(PANTALLAX, PANTALLAY, 16, flags);
pantalla_copia = SDL_CreateRGBSurface(flags,pantalla->w,pantalla->h,pantalla->format->BitsPerPixel,0,0,0,0);




luego con la tecla que quiero cambio de fullscreen a ventana
if(event.key.keysym.sym == SDLK_SPACE )
            {
               //copiamos a pantalla_copia
               SDL_BlitSurface(pantalla,NULL,pantalla_copia,NULL);
               //cambiamos
               flags^=SDL_HWSURFACE | SDL_DOUBLEBUF | SDL_FULLSCREEN;
               pantalla = SDL_SetVideoMode(PANTALLAX, PANTALLAY, 16,flags);
               //rebliteamos la pantalla
               SDL_BlitSurface(pantalla_copia,NULL,pantalla,NULL);



no se si esto te servira de algo o te de alguna idea ;) saludos
Que blitee o no, es lo de menos, ya que la prueba la hago tal y como lo he mostrado, sin dibujar nada (y a la hora de la verdad tampoco tendría sentido porque uso OpenGL). Con la última me refiero a la última 1.2.X. Le has pasado algún programa de análisis de memoria y no te detecta nada? Esque eso es lo que no me explico, cada vez que uso SDL_SetVideoMode 400 bytes se van a tomar por culo.
¿Qué pasa con la estructura SDL_Surface que creas en la primera llamada cuando le asignas el valor de la nueva SDL_Surface en la segunda llamada?
O dicho de otro modo.

¿qué pasa con estos punteros?
int *aPtr;
aPtr = new Class();
aPtr = new Class();


Prueba liberando la superficie de vídeo con SDL_FreeSurface()

Por cierto, en tu código defines el puntero llamado main dos veces :P
zheo escribió:¿Qué pasa con la estructura SDL_Surface que creas en la primera llamada cuando le asignas el valor de la nueva SDL_Surface en la segunda llamada?
O dicho de otro modo.

¿qué pasa con estos punteros?
int *aPtr;
aPtr = new Class();
aPtr = new Class();


Prueba liberando la superficie de vídeo con SDL_FreeSurface()

No es eso, por lo visto las superficies que devuelven SetVideoMode se liberan automáticamente cuando cierras el sistema de vídeo. En cualquier caso, puedes hacer SDL_FreeSurface, tanto antes como después de cerrar el vídeo y no pasará nada.

zheo escribió:Por cierto, en tu código defines el puntero llamado main dos veces :P

Se me fue xD.

Voy a pegar el código mínimo con el que se puede comprobar el memory leak. Si alguien puede hacer el favor de comprobar que efectivamente ocurre, me dejaría muy tranquilo. Para detectarlo, yo uso valgrind (para linux), lo llamas desde consola tal que así "valgrind ./ejecutable", y ya te lo hace todo.

#include "SDL/SDL.h"

int main(int argc,char* argv[]) {
   SDL_Init(SDL_INIT_VIDEO);
   atexit(SDL_Quit);
   SDL_Surface* main = SDL_SetVideoMode (320,240,16,SDL_SWSURFACE);
   //SDL_FreeSurface(main); //no necesario, pero si quereis probar...
   return 0;
}
Si, a mi tambien me pasa. ¿Lo estas probando en un ordenador mas o menos nuevo? A mi me pasa ultimamente con casi todas las librerias y he llegado a la conclusion de que sera mi portatil( a lo mejor el driver de la grafica intel), de hecho mi proyecto de fin de carrera me ha dado estos problemas tanto OpenAL como Ogre3D, y finalmente los he tenido que dejar por imposible y rezar porque no petara el juego en la presentacion XD.
parrincrisis escribió:Si, a mi tambien me pasa. ¿Lo estas probando en un ordenador mas o menos nuevo? A mi me pasa ultimamente con casi todas las librerias y he llegado a la conclusion de que sera mi portatil( a lo mejor el driver de la grafica intel), de hecho mi proyecto de fin de carrera me ha dado estos problemas tanto OpenAL como Ogre3D, y finalmente los he tenido que dejar por imposible y rezar porque no petara el juego en la presentacion XD.

No me digas! pues yo tambien voy a tener que rezar, porque esto tambien va para mi PFC xDDDDDDDD. Mi PC es un Core 2 Duo de un par de años, y la verdad es que yo tambien pense que pudiera ser por los drivers de la grafica... ya me dio algun problema con el compiz fusion que me obligo a desactivarlo bajo amenaza de cuelgue. En mi caso se trata de una ATI Sapphire X550.

Puf, que marrón xD
Siempre podeis recompilar el código en debug y hacer una traza. No es bonito, pero es lo que hay :P
También está la opción de preguntarlo en la lista de correo de SDL.

En cualquier caso voy a ver si configuro el VStudio y lo pruebo en windows. ¿Qué versión de la librería usas?
Es la 1.2.12. Yo esto también lo estoy trabajando con el VS08 por eso de que sea multiplataforma y tal, pero ahí no encuentro ninguna herramienta de análisis de memoria gratuita, que el IBM Purify roza los 1000€ xD. En Windows por tanto, no se si ocurre, porque haciendo el mismo tipo de pruebas que hago en Linux, el programa no se cuelga (aún).

Lo de seguir la traza, no se a que te refieres exactamente... a que haga la traza del código de la SDL?
Elelegido escribió:Es la 1.2.12. Yo esto también lo estoy trabajando con el VS08 por eso de que sea multiplataforma y tal, pero ahí no encuentro ninguna herramienta de análisis de memoria gratuita, que el IBM Purify roza los 1000€ xD. En Windows por tanto, no se si ocurre, porque haciendo el mismo tipo de pruebas que hago en Linux, el programa no se cuelga (aún).

Voy a mirártelo ahora. Yo conozco el visual leak detector, que es algo muy simple pero funciona sólo para el compilador del visual studio. Es un simple .h
http://www.codeproject.com/KB/applicati ... ector.aspx

Por cierto, la última versión estable es la 1.2.13

Lo de seguir la traza, no se a que te refieres exactamente... a que haga la traza del código de la SDL?

Exacto.
Según veo ahora, si que uso la 1.2.13 (en el paquete que me bajé del repositorio así lo indica), lo que pasa es que SDL tiene una función que indica la versión actual (SDL_Linked_Version) y parece que no están actualizados los datos que devuelve. Aquí un tio al que le pasa lo mismo con esto de la versión.

Seguir la traza de la SDL solo me deja una vez desensamblado el código, y.... entender eso me parece muy hardcore xD.

EDIT:

He probado el visual leak detector y yo no se como hacer para que detecte la memoria reservada proveniente de librerias externas. Igual ni se puede, a ver si encuentro algo.
No soy muy experto en SDL, pero no hay alguna forma de indicarle que use vuestros propios allocators via callback por ejemplo, y así véis qué hace?
11 respuestas