Votre question

[Résolu] [C++] Problème de delete

Tags :
  • Programmation
Dernière réponse : dans Programmation
15 Juin 2006 18:57:51

Bonjour à tous !

J'ai un petit problème en C++. Et plus particulièrement avec des delete. Quand je les supprime, tout fonctionne ! Quand je les laisse, j'ai une jolie erreur du type :

L'instruction à "0x77f73aed" emploie l'adresse mémoire "0x00000000". La mémoire ne peut pas être "written".

Et, je ne comprends pas vraiment d'où ça vient. Même si ça doit bien avoir une raison. Voici le code associé à la partie problématique :

  1. extern Block *FocusBlock, *NextBlock;
  2.  
  3. Square** tmp_Array1 = FocusBlock->GetSquares();
  4. Square** tmp_Array2 = NextBlock ->GetSquares();
  5.  
  6. delete FocusBlock, NextBlock;
  7.  
  8. for( char i = 0 ; i<4 ; i++ )
  9. {
  10. delete tmp_Array1[i];
  11. delete tmp_Array2[i];
  12. }
  13.  
  14. for( int j = 0 ; j<OldSquares.size() ; j++ )
  15. {
  16. delete OldSquares[j];
  17. }


La méthode GetSquares() retourne un tableau de pointeurs, comme vous aurez pu le remarquer. Tant qu'à OldSquares, c'est un vector.

Si quelqu'un sait d'où vient l'erreur, je suis preneur ! De même si quelqu'un peut m'expliquer un peu plus en détail le new et le delete. En pratique du moins. Car, la version théorique (avec le malloc), j'ai lu, mais sans plus !

Merci beaucoup ! :-P

Autres pages sur : resolu probleme delete

16 Juin 2006 01:18:45

Citation :

extern Block *FocusBlock, *NextBlock;

Square** tmp_Array1 = FocusBlock->GetSquares();
Square** tmp_Array2 = NextBlock ->GetSquares();

delete FocusBlock, NextBlock;

for( char i = 0 ; i<4 ; i++ )
{
delete tmp_Array1;
delete tmp_Array2;
}

for( int j = 0 ; j<OldSquares.size() ; j++ )
{
delete OldSquares[j];
}


Salut, si il s 'agit de tableaux que tu veux liberer, peut etre devrais-tu essayer "delete []...[.]".
16 Juin 2006 11:02:34

Non, ça ne marche pas beaucoup plus.

D'autres petites précisions cependant... Il semblerait que ce soit pour "deleter" les tableaux que ça bug. J'ai donc explicité la boucle for, et il semblerait que ce soit trois cas bien particuliers qui posent problèmes. Ceux commentés.

  1. delete tmp_Array1[0];
  2. delete tmp_Array1[1];
  3. //delete tmp_Array1[2];
  4. delete tmp_Array1[3];
  5. delete tmp_Array2[0];
  6. //delete tmp_Array2[1];
  7. //delete tmp_Array2[2];
  8. delete tmp_Array2[3];


Je ne sais pas trop d'où ça vient... Quelques indications quand même sur le remplissage de ce tableau...

  1. Square** tmp_Array1 = FocusBlock->GetSquares();
  2. Square** tmp_Array2 = NextBlock ->GetSquares();
  3.  
  4. ---------------------------------------------------
  5. class Block
  6. {
  7. // D'autres choses
  8.  
  9. private:
  10. Square *Squares[4];
  11. }
  12.  
  13. Square** Block::GetSquares(void)
  14. {
  15. return Squares;
  16. }
  17.  
  18. // Création des blocs
  19.  
  20. void Block::SetupSquares(int newX, int newY, SDL_Surface *bitmap)
  21. {
  22. x = newX;
  23. y = newY;
  24.  
  25. for( char i = 0 ; i < 4 ; i++ )
  26. {
  27. // Les delete là fonctionnent.
  28. if( Squares[i] ) delete Squares[i];
  29. }
  30.  
  31. switch(type)
  32. {
  33. case SQUARE_BLOCK: // Center = Center of square [0]
  34. // [0][1]
  35. // [2][3]
  36.  
  37. Squares[0] = new Square( x - SQUARE_SIZE/2, y - SQUARE_SIZE/2, type, bitmap );
  38. Squares[1] = new Square( x + SQUARE_SIZE/2, y - SQUARE_SIZE/2, type, bitmap );
  39. Squares[2] = new Square( x - SQUARE_SIZE/2, y + SQUARE_SIZE/2, type, bitmap );
  40. Squares[3] = new Square( x + SQUARE_SIZE/2, y + SQUARE_SIZE/2, type, bitmap );
  41. break;
  42.  
  43. // Etc... (C'est un Tetris)
  44. }
  45. }
  46.  
  47. --------------------------------------------
  48.  
  49. // Constructeur de la classe Square
  50.  
  51. Square::Square(int x, int y, BlockType type, SDL_Surface *bitmap): x(x), y(y), type(type), bitmap(bitmap){};
  52.  
  53. ----------------------------------------------
  54.  
  55. FocusBlock = new Block(BLOCK_START_X, BLOCK_START_Y, SQUARE_BLOCK, square);
  56. NextBlock = new Block(BLOCK_START_X, BLOCK_START_Y, T_BLOCK, square);


Voilà quelques morceaux de code. Je suis désolé d'en avoir écrit autant (c'est un peu illisible, non ?), mais je pense n'avoir écrit que l'essentiel. Si quelqu'un a une idée...
Contenus similaires
16 Juin 2006 11:18:13

t'as essayé avec free() ?
16 Juin 2006 12:06:10

malloc() et free() sont à éviter en C++, à cause de l'existence des opérateurs new et delete qui rendent les choses plus sûres. Donc, non, je n'ai pas touché à ça.

Après m'être penché un peu plus en avant sur le code, je me suis aperçu que je n'avais pas besoin de supprimer tous les Square de mes Block, à cause du destructeur :

  1. Block::~Block()
  2. {
  3. for( char i = 0 ; i < 4 ; i++ )
  4. {
  5. if( Squares[i] ) delete Squares[i];
  6. }
  7. }


Cependant, en les supprimant, j'ai toujours le même message d'erreur, dû à la suppression des deux blocks. Je patauge complètement là. Je pense mettre les sources sur le Net, histoire que ce soit plus simple.
16 Juin 2006 12:35:30

je crois que tu ne dois pas utiliser une boucle il suffit de mettre dans le destructeur ce code :
Block::~Block()
{
delete [] Square;
}
16 Juin 2006 12:47:50

En effet... Problème résolu ! Tout marche super bien maintenant ! Un très grand MERCI !

Cependant, c'est pas pareil la boucle ?
a b L Programmation
16 Juin 2006 13:06:04

  1. extern Block *FocusBlock, *NextBlock;
  2.  
  3. Square** tmp_Array1 = FocusBlock->GetSquares();
  4. Square** tmp_Array2 = NextBlock ->GetSquares();
  5.  
  6. delete FocusBlock, NextBlock;
  7.  
  8. for( char i = 0 ; i<4 ; i++ )
  9. {
  10. delete tmp_Array1[i];
  11. delete tmp_Array2[i];
  12. }
  13.  
  14. for( int j = 0 ; j<OldSquares.size() ; j++ )
  15. {
  16. delete OldSquares[j];
  17. }

Sinon pour expliquer l'origine du problème:
C'est un problème très classique dans les programmes complexes de double suppression d'un même objet.
ici tu fais un delete sur FocusBlock avant de supprimer son contenu, c'est très dangereux. Si tu veux faire la même chose qui devrait marcher:
  1. extern Block *FocusBlock, *NextBlock;
  2.  
  3. Square** tmp_Array1 = FocusBlock->GetSquares();
  4. Square** tmp_Array2 = NextBlock ->GetSquares();
  5.  
  6. for( char i = 0 ; i<4 ; i++ )
  7. {
  8. delete tmp_Array1[i];
  9. tmp_Array1[i] = 0;
  10. delete tmp_Array2[i];
  11. tmp_Array2[i] = 0;
  12. }
  13.  
  14. for( int j = 0 ; j<OldSquares.size() ; j++ )
  15. {
  16. delete OldSquares[j];
  17. OldSquares[j] = 0;
  18. }
  19.  
  20. delete FocusBlock, NextBlock;


sinon pour la dernière question c'est pareil car delete [] (avec les crochets) appelle le destructeur de chaque élément du tableau, donc plus besoin d'alourdir le code source avec une boucle inutile ;-)
16 Juin 2006 13:22:59

On aurait donc pour résultat :

- instanciation de la classe sur tmp_Array1 et tmp_Array2.
- On vide les attributs de l'objet instancié.
- destruction de l'objet.

Quel est l'intérêt de vider les données de l'objet instancié puisque le destructeur s'en occupe lors de son invocation ?

C'est pour faire du remplissage-vidage de mémoire pour du temps réel ?

Une fois l'objet instancié, les zones réservées en mémoire sont bien allouées ? et déstructurées lors de la destruction par delete ?

delete s'applique uniquement aux objets instanciés ou aux variables privées de la classe ?

:-?

cho le c++
16 Juin 2006 13:47:42

OK. Merci bien de ses quelques informations supplémentaires !

Sinon, même question que Poolos pour les destructeurs. Ils ne peuvent pas se charger du vidage ? Non mais... On les écrit pourquoi ceux-là ? Pour le plaisir ? :-D
a b L Programmation
16 Juin 2006 18:32:56

Citation :
Quel est l'intérêt de vider les données de l'objet instancié puisque le destructeur s'en occupe lors de son invocation ?

Effectivement, ça n'a aucun intérêt, et je dirai même qu'il ne faut jamais le faire. Il faut toujours passer par les destructeurs. Comme ça on n'oublie pas la destruction des données si un objet se détruit implicitement.

Citation :
Une fois l'objet instancié, les zones réservées en mémoire sont bien allouées ? et déstructurées lors de la destruction par delete ?

Par contre, si on fait des new dans les constructeurs, il faut bien penser à faire tous les deletes dans les destructeur.

Citation :

delete s'applique uniquement aux objets instanciés ou aux variables privées de la classe ?

delete détruit l'objet en mémoire et supprime donc implicitement toutes les données qui n'ont pas été créés par un new (des variables membres dans les classes qui ne sont pas des pointeurs mais directement des objets).
19 Juin 2006 14:09:37

Merci pour ces précisions cricky !
19 Juin 2006 15:37:00

De même ! Cricky, notre experte allocation dynamique ! :-)
Tom's guide dans le monde
  • Allemagne
  • Italie
  • Irlande
  • Royaume Uni
  • Etats Unis
Suivre Tom's Guide
Inscrivez-vous à la Newsletter
  • ajouter à twitter
  • ajouter à facebook
  • ajouter un flux RSS