Memory leak

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
AllSystemGo
Posts: 26
Joined: Sat Jun 02, 2007 1:15 am

Memory leak

Post by AllSystemGo »

Hi everyone,

I curently have a problem with memory leak I think. I created a new class that draws all the icons on screen, and for some reason as soon as I create a second icon the PSP goes into a loop the shutdown. If I only create one it paints on the screen perfectly. I'll post what I think is the relevant code.

Main.cpp

Code: Select all


SDL_Surface *ecran = SDL_SetVideoMode(480, 272, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);


Button butCalendar(125, 80, 67, 80, "data/gfx/calendar.png", "Calendar", 15);
Button butSettings(218, 80, 67, 80, "data/gfx/tools.png", "Settings", 15);

    while(isrunning)
    {		
		butCalendar.Render(ecran);
		butSettings.Render(ecran);
		SDL_Flip(ecran);
    }


Button.cpp

Code: Select all

#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <SDL/SDL_ttf.h>

#include <pspkernel.h>
#include <pspdebug.h>
#include <pspctrl.h>
#include <pspdisplay.h>
#include <psprtc.h>

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <string>

#include "Button.h"

using namespace std;

Button&#58;&#58;Button&#40;SDL_Rect bounds, const char *imagePath, const char *text, int fontSize&#41; &#58; Bounds&#40;bounds&#41;, ImagePath&#40;imagePath&#41;, Text&#40;text&#41;, FontSize&#40;fontSize&#41;
&#123;
&#125;

Button&#58;&#58;Button&#40;Sint16 x, Sint16 y, Uint16 width, Uint16 height, const char *imagePath, const char *text, int fontSize&#41; &#58; ImagePath&#40;imagePath&#41;, Text&#40;text&#41;, FontSize&#40;fontSize&#41;
&#123;
	SDL_FreeSurface&#40;TextSurface&#41;;
	SDL_FreeSurface&#40;ImageSurface&#41;;
	
	if&#40;FontObject == NULL&#41;
		FontObject = CreateFont&#40;&#41;;
	if&#40;TextSurface == NULL&#41;
		TextSurface = CreateText&#40;&#41;;
	if&#40;ImageSurface == NULL&#41;
		ImageSurface = CreateImage&#40;&#41;;

	SDL_Rect temp = &#123;x, y, width, height&#125;;
	Bounds = temp;
&#125;

Button&#58;&#58;~Button&#40;&#41;
&#123;
	if&#40;FontObject != NULL&#41;
		TTF_CloseFont&#40;FontObject&#41;;
	if&#40;TextSurface != NULL&#41;
		SDL_FreeSurface&#40;TextSurface&#41;;
	if&#40;ImageSurface != NULL&#41;
		SDL_FreeSurface&#40;ImageSurface&#41;;
&#125;

void Button&#58;&#58;Render&#40;SDL_Surface* screen&#41;
&#123;
	Render&#40;screen, Bounds&#41;;
&#125;

void Button&#58;&#58;Render&#40;SDL_Surface* screen, SDL_Rect bounds&#41;
&#123;
	SDL_Rect imageRect;
	imageRect.y = bounds.y;
	imageRect.x = bounds.x + &#40;bounds.w / 2 - ImageSurface->w / 2&#41;;
	
	SDL_Rect textRect;
	int textWidth;
	int textHeight;
	TTF_SizeText&#40;FontObject, Text, &textWidth, &textHeight&#41;;
	textRect.y = &#40;bounds.y + bounds.h&#41; - textHeight;
	textRect.x = bounds.x + &#40;bounds.w / 2 - textWidth / 2&#41;;	
	
	SDL_BlitSurface&#40;ImageSurface, NULL, screen, &imageRect&#41;;
	SDL_BlitSurface&#40;TextSurface, NULL, screen, &textRect&#41;;
&#125;

bool Button&#58;&#58;Contains&#40;SDL_Rect point&#41;
&#123;
	return point.x >= Bounds.x && point.x <= &#40;Bounds.x + Bounds.w&#41; && 
			point.y >= Bounds.y && point.y <= &#40;Bounds.y + Bounds.h&#41;;
&#125;

TTF_Font* Button&#58;&#58;CreateFont&#40;&#41;
&#123;
	return TTF_OpenFont&#40;"data/font/Rippen.ttf", FontSize&#41;;
&#125;
SDL_Surface* Button&#58;&#58;CreateText&#40;&#41;
&#123;
	SDL_Color white = &#123;255, 255, 255&#125;;

	return TTF_RenderText_Blended&#40;FontObject, Text, white&#41;;
&#125;
SDL_Surface* Button&#58;&#58;CreateImage&#40;&#41;
&#123;
	return SDL_DisplayFormatAlpha&#40;IMG_Load&#40;ImagePath&#41;&#41;;
&#125;
Thank you for your help. If you need more code let me know!!!

Cheers!
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

If you check some of the older threads, you'll find someone else had almost the same problem. You simple can't sit in a loop calling SDL_Flip() or the PSP goes out to lunch. You need something to delay things - a call to sceKernelDelayThread(), a check of the rtc time, a wait on the vbl...
AllSystemGo
Posts: 26
Joined: Sat Jun 02, 2007 1:15 am

Post by AllSystemGo »

I do understand what you are saying J.F. but the thing is if I remove the Button butSettings(xxxxx); and the butSettings.Render(ecran);

Everything loads perfectly. That is my concern, why when I declare a second button the PSP stays black for 15 seconds then shutdown...

Thxs
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

Okay. I don't see a TTF_Init() in there, and you might try checking if the CreateFont() (and other similar calls in Button) fail. Your code just assumes that all calls are working without error. Maybe the second Button created has one of them failing.
danzel
Posts: 182
Joined: Fri Nov 04, 2005 11:03 pm

Post by danzel »

Code: Select all

Button&#58;&#58;Button&#40;Sint16 x, Sint16 y, Uint16 width, Uint16 height, const char *imagePath, const char *text, int fontSize&#41; &#58; ImagePath&#40;imagePath&#41;, Text&#40;text&#41;, FontSize&#40;fontSize&#41;
&#123;
   SDL_FreeSurface&#40;TextSurface&#41;;
   SDL_FreeSurface&#40;ImageSurface&#41;; 
   
   if&#40;FontObject == NULL&#41;
      FontObject = CreateFont&#40;&#41;;
   if&#40;TextSurface == NULL&#41;
      TextSurface = CreateText&#40;&#41;;
   if&#40;ImageSurface == NULL&#41;
      ImageSurface = CreateImage&#40;&#41;; 
Why do you free these surfaces in the constructor, and then optionally recreate them?

They could be uninitialised variables (Hard to tell if they are from the code pasted), and SDL_FreeSurface()'ing them would be bad, possibly crashable.
AllSystemGo
Posts: 26
Joined: Sat Jun 02, 2007 1:15 am

Post by AllSystemGo »

Thank you for the replies. I will check into the TTF_Init missing, and for Danzel the FreeSurface wasn't there before and it still crashed, I'll remove that and try with the TTF_Init

Thank you again.
AllSystemGo
Posts: 26
Joined: Sat Jun 02, 2007 1:15 am

Post by AllSystemGo »

Still the same problem. I'll repost my main.cpp and the class

main.cpp

Code: Select all

/*
iPDA
June 18 2007
*/

#include <pspkernel.h>
#include <pspdebug.h>
#include <pspctrl.h>
#include <pspdisplay.h>
#include <psppower.h>
#include <psprtc.h>
#include <png.h>

#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <SDL/SDL_ttf.h>

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <string>
#include <list>
#include <iostream>
#include <fstream>

#include "alarm.h"
#include "alarmmanager.h"
#include "button.h"

using namespace std;

PSP_MODULE_INFO&#40;"iPDA", 0, 1, 1&#41;;
PSP_MAIN_THREAD_ATTR&#40;THREAD_ATTR_USER | THREAD_ATTR_VFPU&#41;;

static bool isrunning = true;
static int curWindow = 1;

// Exit callback
int exit_callback&#40;int arg1, int arg2, void *common&#41; &#123;
	isrunning = false;
	sceKernelExitGame&#40;&#41;;
	return 0;
&#125;

// Callback thread 
int CallbackThread&#40;SceSize args, void *argp&#41; &#123;
	int cbid; 
	
	cbid = sceKernelCreateCallback&#40;"Exit Callback", exit_callback, NULL&#41;;
	sceKernelRegisterExitCallback&#40;cbid&#41;;
	
	sceKernelSleepThreadCB&#40;&#41;;
 	
	return 0;
&#125;

// Sets up the callback thread and returns its thread id
int SetupCallbacks&#40;void&#41; &#123;
	int thid = 0;
 	
	thid = sceKernelCreateThread&#40;"update_thread", CallbackThread, 0x11, 0xFA0, 0, 0&#41;;
	if&#40;thid >= 0&#41;
	&#123;
		sceKernelStartThread&#40;thid, 0, 0&#41;;
	&#125;
 	
	return thid;
&#125;

int main&#40;&#41; &#123;
	 //Initialize the controler
    SceCtrlData pad;
    sceCtrlSetSamplingCycle&#40;0&#41;;
    sceCtrlSetSamplingMode&#40;PSP_CTRL_MODE_ANALOG&#41;;
	 u64 CurTick;
	 u64 CmpTick;
	 char timeText&#91;8&#93;;
	
	 sceRtcGetCurrentTick&#40;&CmpTick&#41;;
	
	 //Initialize the PSP Time
	 pspTime time;
    
	 //Initialize the SDL Library &#40;audio and video&#41;
    if&#40;SDL_Init&#40;SDL_INIT_VIDEO&#41; < 0&#41;
		cout << stderr << "Couldn't initialize SDL&#58; " << SDL_GetError&#40;&#41; << endl;

    //Initialize the SDL True Type Font Library
    if&#40;TTF_Init&#40;&#41; < 0&#41;
		cout << stderr << "Couldn't initialize TTF&#58; " << SDL_GetError&#40;&#41; << endl;

    //Initialize the font color.
    SDL_Color white = &#123;255, 255, 255&#125;;
	 SDL_Color black = &#123;0, 0, 0&#125;;
	
	 //Initializing the images and text.
		Button butCalendar&#40;125, 80, 67, 80, "data/gfx/calendar.png", "Calendar", 15&#41;;
		Button butSettings&#40;218, 80, 67, 80, "data/gfx/tools.png", "Settings", 15&#41;;
		

    //Initialize the mouse.
    SDL_Rect mouse = &#123;239, 134&#125;;

    //Initialize the Joystick.
    SDL_Rect posJoy;
	 posJoy.x = pad.Lx-128;
    posJoy.y = pad.Ly-128;
					
    SDL_Surface *ecran = SDL_SetVideoMode&#40;480, 272, 32, SDL_HWSURFACE | SDL_DOUBLEBUF&#41;;
	
	 SDL_Surface *textTime = NULL;

    //Initialize the callbacks
	 pspDebugScreenInit&#40;&#41;;
    SetupCallbacks&#40;&#41;;
		
    //Start the loop
    while&#40;isrunning&#41;
    &#123;		
		sceCtrlReadBufferPositive&#40;&pad, 1&#41;; //Read the joystick
		sceRtcGetCurrentClockLocalTime&#40;&time&#41;; //Get the current time
		
		//Move the mouse on screen
      if&#40;&#40;pad.Lx < 35&#41; && &#40;mouse.x > 0&#41;&#41;
		&#123;
			mouse.x = mouse.x-3;
		&#125;
		else if&#40;&#40;pad.Lx > 200&#41; && &#40;mouse.x < 480&#41;&#41;
		&#123;
			mouse.x = mouse.x+3;
		&#125;
		
		if&#40;&#40;pad.Ly < 35&#41; && &#40;mouse.y > 0&#41;&#41;
		&#123;
			mouse.y = mouse.y-3;
		&#125;
		else if&#40;&#40;pad.Ly > 200&#41; && &#40;mouse.y < 480&#41;&#41;
		&#123;
			mouse.y = mouse.y+3;
		&#125;
		
		// Don't let the mouse go off screen
      if&#40;mouse.x >= 470&#41;&#40;mouse.x = 470&#41;;
		if&#40;mouse.y >= 265&#41;&#40;mouse.y = 265&#41;;
		
		sceRtcGetCurrentTick&#40;&CurTick&#41;;
		
		 //Verify that a second passed before blitting the new clock. This was done to correct the problem were the clock disapear for blitting to many times.
      if &#40;sceRtcCompareTick&#40;&CurTick, &CmpTick&#41; >= 0&#41;
		&#123;
			SDL_FreeSurface&#40;textTime&#41;;
			snprintf&#40;timeText, 8, "%02i &#58; %02i", time.hour, time.minutes&#41;;
			
			textTime = TTF_RenderText_Shaded&#40;timeFont, timeText, white, black&#41;;

			sceRtcGetTick&#40;&time, &CmpTick&#41;;
			sceRtcTickAddMinutes&#40;&CmpTick, &CmpTick, 1&#41;;
			SDL_BlitSurface&#40;textTime, NULL, ecran, &txttime_position&#41;;
		&#125;
	
		if &#40;curWindow == 1&#41;
		&#123;
		   if &#40;pad.Buttons & PSP_CTRL_CROSS&#41;
			&#123;
				if &#40;&#40;mouse.x > calculator_position.x&#41; && &#40;mouse.x < &#40;calculator_position.x + 64&#41;&#41; &&
				    &#40;mouse.y > calculator_position.y&#41; && &#40;mouse.y < &#40;calculator_position.y + 64&#41;&#41;&#41;
				&#123;
					curWindow = 2;
				&#125;
			&#125;
			
			butCalendar.Render&#40;ecran&#41;;
			butSettings.Render&#40;ecran&#41;;
		&#125;
		
		SDL_BlitSurface&#40;mousePointer, NULL, ecran, &mouse&#41;;		
		SDL_Flip&#40;ecran&#41;;
    &#125;
	
    //Free the memory.
	
    SDL_FreeSurface&#40;mousePointer&#41;;

	 TTF_Quit&#40;&#41;;
    SDL_Quit&#40;&#41;;
	
    sceKernelSleepThread&#40;&#41;;

    return 0;
&#125;

button.cpp

Code: Select all

#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <SDL/SDL_ttf.h>

#include <pspkernel.h>
#include <pspdebug.h>
#include <pspctrl.h>
#include <pspdisplay.h>
#include <psprtc.h>

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <string>
#include <iostream>
#include <fstream>

#include "button.h"

using namespace std;

Button&#58;&#58;Button&#40;SDL_Rect bounds, const char *imagePath, const char *text, int fontSize&#41; &#58; Bounds&#40;bounds&#41;, ImagePath&#40;imagePath&#41;, Text&#40;text&#41;, FontSize&#40;fontSize&#41;
&#123;
&#125;

Button&#58;&#58;Button&#40;Sint16 x, Sint16 y, Uint16 width, Uint16 height, const char *imagePath, const char *text, int fontSize&#41; &#58; ImagePath&#40;imagePath&#41;, Text&#40;text&#41;, FontSize&#40;fontSize&#41;
&#123;
	
	FontObject = CreateFont&#40;&#41;;
	TextSurface = CreateText&#40;&#41;;
	ImageSurface = CreateImage&#40;&#41;;
	
	SDL_Rect temp = &#123;x, y, width, height&#125;;
	Bounds = temp;
&#125;

Button&#58;&#58;~Button&#40;&#41;
&#123;
	if&#40;FontObject != NULL&#41;
		TTF_CloseFont&#40;FontObject&#41;;
	if&#40;TextSurface != NULL&#41;
		SDL_FreeSurface&#40;TextSurface&#41;;
	if&#40;ImageSurface != NULL&#41;
		SDL_FreeSurface&#40;ImageSurface&#41;;
&#125;

void Button&#58;&#58;Render&#40;SDL_Surface* screen&#41;
&#123;
	Render&#40;screen, Bounds&#41;;
&#125;

void Button&#58;&#58;Render&#40;SDL_Surface* screen, SDL_Rect bounds&#41;
&#123;
	SDL_Rect imageRect;
	imageRect.y = bounds.y;
	imageRect.x = bounds.x + &#40;bounds.w / 2 - ImageSurface->w / 2&#41;;
	
	SDL_Rect textRect;
	int textWidth;
	int textHeight;
	TTF_SizeText&#40;FontObject, Text, &textWidth, &textHeight&#41;;
	textRect.y = &#40;bounds.y + bounds.h&#41; - textHeight;
	textRect.x = bounds.x + &#40;bounds.w / 2 - textWidth / 2&#41;;	
	
	SDL_BlitSurface&#40;ImageSurface, NULL, screen, &imageRect&#41;;
	SDL_BlitSurface&#40;TextSurface, NULL, screen, &textRect&#41;;
&#125;

bool Button&#58;&#58;Contains&#40;SDL_Rect point&#41;
&#123;
	return point.x >= Bounds.x && point.x <= &#40;Bounds.x + Bounds.w&#41; && 
			point.y >= Bounds.y && point.y <= &#40;Bounds.y + Bounds.h&#41;;
&#125;

TTF_Font* Button&#58;&#58;CreateFont&#40;&#41;
&#123;
	return TTF_OpenFont&#40;"data/font/Rippen.ttf", FontSize&#41;;
&#125;
SDL_Surface* Button&#58;&#58;CreateText&#40;&#41;
&#123;
	SDL_Color white = &#123;255, 255, 255&#125;;
	
	if&#40;FontObject == NULL&#41;
		CreateFont&#40;&#41;;
	
	return TTF_RenderText_Blended&#40;FontObject, Text, white&#41;;
&#125;
SDL_Surface* Button&#58;&#58;CreateImage&#40;&#41;
&#123;
	return SDL_DisplayFormatAlpha&#40;IMG_Load&#40;ImagePath&#41;&#41;;
&#125;
I still get the same problem. If I remove the Button butSettings everything loads up perfectly but as soon as I add the second button then the PSP stay black for about 10 seconds then shutdown.

Thanks for your help.

Cheers.
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

You're still not checking if your surfaces are created. Try adding a check in the Render function.

Code: Select all

   if &#40;ImageSurface != NULL&#41;
      SDL_BlitSurface&#40;ImageSurface, NULL, screen, &imageRect&#41;;
   if &#40;TextSurface != NULL&#41;
      SDL_BlitSurface&#40;TextSurface, NULL, screen, &textRect&#41;;
If that works, then you know that one of the surfaces fails to be created the second time a button is created. Your program has very little error checking - it's something you need to worry about, at least until you get the bugs worked out.
Post Reply