Bonjour à tous,
débutant en C++ (mais déjà confirmé en Java, donc pas débutant en programmation), je suis confronté à un problème de mémoire que je ne comprend pas (n'ayant jamais eu à gêrer la mémoire auparavent). Le programme est un petit jeu en 2D.
J'utilise Visual C++ .net, et mon problème se situe dans une liste (std::list). J'utilise une liste de pointeurs vers des objets (list<GameObject*>) dont j'actualise l'état et que j'affiche grâce à la méthode GameObject::refresh().
voici le code:
Parmis ces GameObject à actualiser et afficher, deux sous-classe sont incriminée : Sea et Boat.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 void GameState::render() { list<GameObject*>::iterator iter; for( iter = m_renderable_objects.begin(); iter != m_renderable_objects.end(); iter++) { if(!((*iter)->getParent())) (*iter)->refresh(SDL_GetTicks()); } }
Boat possède une liste de GameObject enfants. On a donc (en simplifiant le vrai code) :
Sea, quand à elle, dessine dans son Sea::refresh() une spline, et donc possède un double *m_second_derivative qui sert à stocker un tableau de double représentant la dérivée seconde des points de contrôles de la spline (il s'agit d'une spline cubique).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 void Boat::refresh(int _time) { list <GameObject *>::iterator end = m_children.end(); for (list <GameObject *>::iterator iter = m_children.begin(); iter != end; ++iter) { (*iter)->refresh(_time); }
Voilà donc le code (simplifié là encore) :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 void Sea::refresh(int _time) { animate(); calculateSecondDerivative(); display(); } void Sea::calculateSecondDerivative() { double yp0 = (m_ctrl_points[1].getY()-m_ctrl_points[0].getY()) / (m_ctrl_points[1].getX()-m_ctrl_points[0].getX()); double ypnm1 = (m_ctrl_points[m_nb_ctrl_points-1].getY()-m_ctrl_points[m_nb_ctrl_points-2].getY()) / (m_ctrl_points[m_nb_ctrl_points-1].getX()-m_ctrl_points[m_nb_ctrl_points-2].getX()); int i,k; double p,qn,sig,un,*u; u = new double[m_nb_ctrl_points]; //evite la pente initiale trop importante if (yp0 > 1e30) m_second_derivative[0]=u[0]=0.0; else { m_second_derivative[0] = -0.5; u[0]=(3.0/(double)(m_ctrl_points[1].getX()-m_ctrl_points[0].getX()))*((double)(m_ctrl_points[1].getY()-m_ctrl_points[0].getY()) / (double)(m_ctrl_points[1].getX()-m_ctrl_points[0].getX())-yp0); } for (i=1;i<m_nb_ctrl_points-1;i++) { sig=(double)(m_ctrl_points[i].getX()-m_ctrl_points[i-1].getX())/(double)(m_ctrl_points[i+1].getX()-m_ctrl_points[i-1].getX()); p=sig*m_second_derivative[i-1]+2.0; m_second_derivative[i]=(sig-1.0)/p; u[i]=(double)(m_ctrl_points[i+1].getY()-m_ctrl_points[i].getY())/(float)(m_ctrl_points[i+1].getX()-m_ctrl_points[i].getX()) - (double)(m_ctrl_points[i].getY()-m_ctrl_points[i-1].getY())/(double)(m_ctrl_points[i].getX()-m_ctrl_points[i-1].getX()); u[i]=(6.0*u[i]/(double)(m_ctrl_points[i+1].getX()-m_ctrl_points[i-1].getX())-sig*u[i-1])/p; } //evite la pente finale trop importante if (ypnm1 > 0.99e30) qn=un=0.0; else { qn=0.5; un=(3.0/(double)(m_ctrl_points[m_nb_ctrl_points-1].getX()-m_ctrl_points[m_nb_ctrl_points-2].getX()))*(ypnm1-(double)(m_ctrl_points[m_nb_ctrl_points-1].getY() - m_ctrl_points[m_nb_ctrl_points-2].getY())/(double)(m_ctrl_points[m_nb_ctrl_points-1].getX()-m_ctrl_points[m_nb_ctrl_points-2].getX())); } m_second_derivative[m_nb_ctrl_points-1]=(un-qn*u[m_nb_ctrl_points-2])/(qn*m_second_derivative[m_nb_ctrl_points-2]+1.0); for (k=m_nb_ctrl_points-2;k>=0;k--) m_second_derivative[k]=m_second_derivative[k]*m_second_derivative[k+1]+u[k]; delete [] u; }
Et si vous êtes encore là (je sais que cet exposé est un peu long, mais j'ai peur de ne pas être clair !), voilà où est le problème :
lors de la première itération de ma boucle principale de jeu, les adresses mémoires de la liste Boat::m_children sont les suivantes (d'après le debugger) :
la liste ne contient qu'un élément et j'observe bien m_children::_Mysize = 1
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 m_children::Myhead 0x003e2b60 m_children::_Next 0x003e5bd8 m_children::_Prev 0x003e5bd8
eh bien juste après le passage dans Sea::calculateSecondDerivative(), qui est affiché juste après, ces valeurs changent pour des valeurs bizarres :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 m_children::Myhead 0x003e2b60 m_children::_Next 0x503e382b m_children::_Prev 0xbeccc318
evidemment, dès la deuxième itération, le programme plante avec un joli "Access violation reading location 0x503e382b", ce qui me parait logique.
Ce qui m'est incompréhensible, c'est comment le remplissage d'un tableau de double dans une classe peut agir sur les adresses d'une liste qui est dans une autre classe...
Peut-être est-ce le symptôme d'un problème qui vient d'ailleur, mais je ne sais pas du tout où regarder...
Quelqu'un aurait-il une piste ?
Antoine
Partager