Nop90 Spectre

Inscrit le: 04 Juin 2016 Age: 55
Messages: 1
|
Posté le: Sam Juin 04, 2016 16:16 Sujet du message: Some bug fix for ROTH and maybe the other games |
|
|
I just finished a port of ZELDA ROTH on 3DS (it's opensource on github, you can find it with google) and I found some bugs causing a memory leak.
On a 3DS there is a limited amount of memory available and every small memory leak can cause a crash, so I had to remove all of them.
Here is a list of the fixes I made in case the coders of this great fan game want to use them in their code.
1.
Loading a save game there is a call to gpJeu->Init(save) that creates some other classes without releasing the alreasy existing.
I created a metod reInit that deletes the existing objects before creating the new one:
Code: |
void Jeu::reinit(int save) {
zone=21;
delete gpProjectile;
gpProjectile = new Projectile(this, 0, N, 0, 0, 0);
delete gpObjet;
gpObjet = new Objet(this, 0, 0, 0, 0);
delete gpSnipe;
gpSnipe = new Snipe(this, 0, 0, 0, 0, 0);
delete gpCaisse;
gpCaisse = new Caisse(this, 0, 0, 0);
delete gpEnnemi;
gpEnnemi = new Ennemi(this, 0, 0, 0, true);
delete gpPiege;
gpPiege = new Ennemi(this, 0, 0, 0, true);
delete gpPnj;
gpPnj = new Pnj(this, 0, 0, 0, 0);
delete gpJoueur;
gpJoueur = new Joueur(this, save);
delete gpMonde;
gpMonde = new Monde(this);
delete gpMenu;
gpMenu = new Menu(this);
//gpTexte = new Texte(this);
delete gpStatut;
gpStatut = new Statut(this);
gpAudio->playMusic(zone);
if (isDonjon()) ecrit(206+zone-12);
}
|
2.
in void Generique::initSelection() there is a loop that creates a temporary Jouer object that is not released at the end of every cicle of the loop. I added a delete statement:
Code: |
…
for (int i = 0; i < 3; i++) {
Joueur* gpJoueur = new Joueur(gpJeu,i+1);
if (gpJoueur->getLoader()) {
//vie
if(gpJoueur->getVie()>gpJoueur->getVieMax()) gpJoueur->setVie(gpJoueur->getVieMax());
for(int j=0;j<gpJoueur->getVieMax()/2;j++) {
src.h = 7; src.w = 7; src.y=9;
dst.x = 64+((j%10)*8)+8;dst.y = 57+8*((int)(j/10))+i*48;
if (gpJoueur->getVie()-(j*2)>1)src.x=141;
if (gpJoueur->getVie()-(j*2)==1)src.x=149;
if (gpJoueur->getVie()-(j*2)<1)src.x=157;
SDL_BlitSurface(imageStat, &src, image, &dst);
}
//cristaux
dst.x=176+8-16; dst.y=56+i*48;
src.x=16; src.y=17*4; src.w=16; src.h=17;
for (int j=0; j<7; j++) {
if (gpJoueur->hasCristal(j)) src.x=16; else src.x=32;
SDL_BlitSurface(inventaire, &src, image, &dst);
dst.x+=16-3;
}
//triforce
dst.x=272; dst.y=56+i*48;
src.x=128; src.y=0; src.w=17; src.h=16;
if (gpJoueur->getEnnemi(50)) SDL_BlitSurface(objets, &src, image, &dst);
gpJeu->getKeyboard()->setSave(i,1);
}else gpJeu->getKeyboard()->setSave(i,0);
delete gpJoueur;
}
|
3.
Last, all the classes derived from Listable have a problem in the destructor because all the element after the first in the list are destroied with the destructor of the base class (Listable) and not of the derived class. So everithing created in the constructor of the derived class is not released.
To solve this I intoduced in the destructor of every derived class a workaround that saves in a temp variable the suivant pointer, blocks the Listable destructor setting suivant=NULL (to avoid to call twice the Listable destructor) and then delete the object pointed by the temp variable with an explicit cast to the correct object type.
Here is an example for the caisse Class:
Code: |
Caisse::~Caisse() {
if(suivant) {
Caisse* temp;
temp = (Caisse*)suivant;
suivant=NULL;
delete temp;
}
}
|
Hope this helps.
regards, NOP90 |
|