Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: Ceiplusplus en 4 Julio 2016, 17:54 pm



Título: Memory leak ~~new + delete + SDL~~
Publicado por: Ceiplusplus en 4 Julio 2016, 17:54 pm
Hola a todos, tengo una gran duda desde hace unos 2 días y no consigo resolverla, espero que podáis echarme una mano :-\
estoy programando un minijuego en C++ y SDL. El problema esta dentro de la clase Imagen, la cual utilizo para almacenar una imagen y sus propiedades, al crear un objeto de esta clase utilizando memoria dinámica y posteriormente borrándolo, este sigue consumiendo la misma memoria que tenía una vez hecha la reserva y no entiendo muy bien el por qué. Os pongo aquí el fragmento de código que utilicé para intentar descubrir que es lo que fallaba.
-------------------------------------------

#include <iostream>
#include <SDL.h>
#include <SDL_image.h>

class Imagen;

class Imagen
{
private:
   SDL_Texture* m_textura;
   SDL_Renderer* m_renderer;
public:
   Imagen(SDL_Renderer* rend, std::string ruta);
   ~Imagen();
};

#define      FONDO_1         "./Recursos/desarmado.png"

#undef main;

int main(int argc, char* argv)
{
   SDL_Init(SDL_INIT_EVERYTHING);
   IMG_Init(IMG_INIT_PNG);
   bool bandera = true;
   SDL_Window* mi_ventana=NULL;

   mi_ventana=SDL_CreateWindow("Prueba Memory leak", 100, 100, 500, 500, SDL_WINDOW_SHOWN);
   SDL_Renderer* m_renderer=NULL;
   m_renderer = SDL_CreateRenderer(mi_ventana, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
   
   if (m_renderer == NULL)
      std::cout << "Error" << std::endl;

   SDL_Event e;
   Imagen*   m_imagen=NULL;
   
   while (bandera)
   {
      while (SDL_PollEvent(&e) != 0)
      {
         if (e.type == SDL_KEYDOWN)
         {
            if (e.key.keysym.sym == SDLK_c) //cargamos imagen
            {
               m_imagen = new Imagen(m_renderer, FONDO_1);
            }
            else if (e.key.keysym.sym == SDLK_r)// descargamos imagen
            {
               if (m_imagen != NULL)
               {
                  delete(m_imagen);
                  m_imagen = NULL;
                  std::cout << "Borrando..." << std::endl;
               }
            }
         }
         else if (e.type == SDL_QUIT)
         {
            bandera = false;
         }
      }

      SDL_Delay(50);
   }

   SDL_Quit();
   IMG_Quit();

   return 0;
}

Imagen::Imagen(SDL_Renderer* rend, std::string ruta):m_renderer(rend), m_textura(NULL)
{
   SDL_Surface* m_superficie = NULL;
   SDL_Texture* m_textura = NULL;

   m_superficie = IMG_Load(FONDO_1);

   m_textura = SDL_CreateTextureFromSurface(m_renderer, m_superficie);

   if (m_superficie != NULL)
      SDL_FreeSurface(m_superficie);
}

Imagen::~Imagen()
{
   SDL_DestroyTexture(m_textura);
   m_textura = NULL;
}


-------------------------------------------
El programa funciona tal que así:

empiezo inicializando una ventana (SDL_window*) y creo un contexto (SDL_Renderer*) para dibujar en pantalla y poder transformar las superficies (imagen) en texturas (como las superficies pero se dibujan mas rápido en pantalla o eso tengo entendido :laugh:), posteriormente declaro un puntero a un objeto Imagen, y creo un bucle donde se realizan dos operaciones, al pulsar 'c' del teclado creo un objeto de la clase Imagen que carga una imagen determinada, y al pulsar 'r' borro el objeto creado.

En el fragmento de código utilizo SDL.h y SDL_image.h

PD: Las funciones SDL_FreeSurface y SDL_DestroyTexture funcionan correctamente, el problema viene al meter como miembro de una clase, SDL_Texture* y hacer las operaciones dentro de la clase.

Espero respuestas gracias de antemano ;D


Título: Re: Memory leak ~~new + delete + SDL~~
Publicado por: AlbertoBSD en 4 Julio 2016, 18:06 pm
Como estas validando la cantidad de memoria utilizada?

ten en cuenta que cuando se libera un segmento de memoria esto solo me marca como "Libre", pero no significa que esa memoria (Asignada por el sistema Operativo) va a dejar de pertenecer al programa de forma instantánea, eso es tarea del sistema operativo que después de un tiempo de no utilizar la memoria, se le des-Asigna al programa.

Por ejemplo he hecho programas que cargan el contenido de un archivo en memoria y por la forma en la que esta hecho al principio sube hasta los 200MB de memoria usada y despues de unos varios minutos de estar procesando mas datos, va bajando a lo que realemnte esta usando unos 10-15 MB que es cuando ya se dejo de usar mucha memoria y el sistema se la des-asigno al proceso.

Saludos


Título: Re: Memory leak ~~new + delete + SDL~~
Publicado por: Ceiplusplus en 4 Julio 2016, 19:31 pm
En visual studio, con las herramientas de diagnostico se puede mirar la cantidad de memoria utilizada en la aplicación cuando cargo la imagen, esto es, creo un objeto y en el objeto cargo la imagen. Las pruebas que he hecho son las siguientes:

en el main, cree una instancia SDL_Texture y le cargué una imagen, al cargarla, en las herramientas de diagnostico subió la memoria y al borrar el SDL_Texture vuelve al estado de memoria inicial al que estaba antes de cargar la imagen. (Esto es lo que creo que debería hacer el programa siempre).

La otra prueba, es hacer exactamente lo mismo pero el SDL_Texture esta dentro de un objeto de la clase Imagen, al crear el objeto, la memoria sube, y al borrarlo, se mantiene esa memoria, como si el objeto siguiera existiendo.

He probado lo que me dijiste, pero después de varios minutos de esperar tras haber borrado el objeto (aprox. 4 minutos) la memoria sigue estando en el mismo punto.

¿Hay alguna forma de arreglarlo?
No se si será el problema de que C++ no tiene el 'colector de basura' como tiene java o c# pero debe de haber alguna forma para hacer que esto no pase ¿no?

Por cierto, gracias por la respuesta AlbertoBSD.


Título: Re: Memory leak ~~new + delete + SDL~~
Publicado por: AlbertoBSD en 4 Julio 2016, 20:46 pm
Ahi desconozco como se comporte, igual podrias darle mas tiempo al programa ooo tratar de liberar la instancia del objeto a ver si ahora si libera toda esa memoria referenciada por el objeto.

Saludos


Título: Re: Memory leak ~~new + delete + SDL~~
Publicado por: Ceiplusplus en 5 Julio 2016, 15:35 pm
¿como libero la instancia del objeto?
Resulta que en el juego que estoy haciendo tengo varias plantillas de animaciones por lo que me obliga a estar cambiando de imágenes constantemente, es decir creando y destruyendo la clase Imagen, esto es:
el personaje coge arma a dos manos, descargo las imágenes de las animaciones anteriores del personaje y cargo ahora las de 2 manos.

He estado mirando por internet pero no mucha gente da información acerca del problema, hay gente que aconseja los smart pointers pero no funcionan bien en el sentido de que debes estar constantemente creándolos, pues mucho de ellos solo trabajan en el bloque que los creas y sinceramente he probado cambiar los contenidos del smart pointer y no encuentro la manera.

Otra posible solución que ya he probado y no ha funcionado es crear la instancia de la clase dentro de un vector y utilizarunl iterador o los propios métodos del vector para liberar bien la memoria.

 :-X :-X Espero respuesta!! :-X :-X


Título: Re: Memory leak ~~new + delete + SDL~~
Publicado por: Ceiplusplus en 12 Julio 2016, 18:20 pm
Ya he corregido lo que pasaba, no se el porqué, ni he conseguido encontrar el porque pasaba en internet, pero lo he solucionado de la siguiente manera, colocar la textura (SDL_Texture*) dentro de un std::vector y con un iterador acceder a la textura almacenada dentro del vector y borrarla utilizando SDL_DestroyTexture (el vector estaba dentro de la clase).  ;-) ;-) ;-)