IdentifiantMot de passe
Loading...
Mot de passe oubli� ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les r�ponses en temps r�el, voter pour les messages, poser vos propres questions et recevoir la newsletter

Visual C++ Discussion :

[compilo Visual 2005] Fonctionnement du delete


Sujet :

Visual C++

Vue hybride

Message pr�c�dent Message pr�c�dent   Message suivant Message suivant
  1. #1
    Membre �prouv�
    Homme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Avril 2007
    Messages
    142
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 43
    Localisation : France, Val de Marne (�le de France)

    Informations professionnelles :
    Activit� : Ing�nieur d�veloppement logiciels
    Secteur : High Tech - �diteur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 142
    Par d�faut [compilo Visual 2005] Fonctionnement du delete
    Bonjour � tous,

    J'ai une question sur le fonctionnement de l'op�rateur delete en debug avec le compilo de Visual 2005.
    Pour vous donner le contexte, nous devons r�aliser un container de type anneau.
    Nous avons tout d'abord une structure de type liste chain�e :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    struct tNode
    {
     T* elt;
     tNode* next_elt;
    }
    Nous avons ensuite une classe dans laquelle nous allouons au constructeur un tableau de tNode:
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    tNode* nodes = new tNode[size_max+1];
    Et enfin dans le destructeur de la classe, nous devons d�sallouer bien sur. Mais nous ne pouvons utiliser l'op�rateur delete[] car certains �l�ments pourraient encore �tre utilis�s ailleurs.
    Nous faisons donc une boucle sur les �l�ments � lib�rer, mais voil� le delete semble lib�rer tout le tableau.

    Concr�tement, voici ce que nous avons en m�moire apr�s allocation:
    0x003663CC fd fd fd fd ����
    0x003663D0 00 00 00 00 ....
    0x003663D4 d8 63 36 00 �c6.
    0x003663D8 00 00 00 00 ....
    0x003663DC e0 63 36 00 �c6.
    0x003663E0 00 00 00 00 ....
    0x003663E4 e8 63 36 00 �c6.
    0x003663E8 00 00 00 00 ....
    0x003663EC d0 63 36 00 �c6.
    0x003663F0 fd fd fd fd ����
    Le tableau commence � 0x003663D0 et se finit � 0x003663EC, pas de probl�me.
    Nous d�clarons un pointeur sur le 1er �lement du tableau, puis nous faisons un delete sur ce pointeur:
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    tNode* elt = nodes[0];
    delete elt;
    o� front est un attribut de la classe qui pointe vers le 1er �l�ment du tableau.
    Et voila ce que nous avons en m�moire apr�s ces instructions :
    0x003663CC ee fe ee fe ����
    0x003663D0 ee fe ee fe ����
    0x003663D4 ee fe ee fe ����
    0x003663D8 ee fe ee fe ����
    0x003663DC ee fe ee fe ����
    0x003663E0 ee fe ee fe ����
    0x003663E4 ee fe ee fe ����
    0x003663E8 ee fe ee fe ����
    0x003663EC ee fe ee fe ����
    0x003663F0 ee fe ee fe ����
    Apparemment le tableau a �t� lib�r� dans son int�gralit� !! Comme si nous avions fait un delete[], ce que nous voulions justement �viter.
    J'aimerais donc savoir si c'est bien le compilo Visual qui ne respecte pas la norme, et qui d�salloue jusqu'� rencontrer fd fd fd fd, alors qu'il ne devrait d�sallouer que l'�l�ment point� par elt ?

    Merci par avance pour votre aide.

  2. #2
    R�dacteur
    Avatar de Neitsa
    Homme Profil pro
    Chercheur s�curit� informatique
    Inscrit en
    Octobre 2003
    Messages
    1 041
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activit� : Chercheur s�curit� informatique

    Informations forums :
    Inscription : Octobre 2003
    Messages : 1 041
    Par d�faut
    Bonjour,

    C'est un comportement normal. Le probl�me vient du fait que tu alloues une tableau de tNode:

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
     
    tNode* nodes = new tNode[size_max+1];
    Alors que c'est plus probablement un tableau de pointeur de tNode que tu souhaitais (comme �a tu peux lib�rer n'importe quel objet du tableau sans lib�rer le tableau entier). Du coup, � la lib�ration, c'est tout le tableau qui disparait.

    Code minimal du probl�me:

    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
     
    typedef struct _TNODE{
     
    	int elem;
    	struct _TNODE* next;
     
    }TNODE, *PTNODE;
     
    #define MAX_SIZE 10
    int main(int argc, char* argv[])
    {	
    	PTNODE nodes = new TNODE[MAX_SIZE];
     
    	for(int i = 0; i < MAX_SIZE; i++)
    	{
    		nodes[i].elem = i;
    		if(i < MAX_SIZE - 1)
    			nodes[i].next = &nodes[i+1];
    		else
    			nodes[i].next = &nodes[0];
    	}
     
    	delete nodes; //libère tout le tableau!
     
    	return 0;
    }
    Ce que tu souhaites faire, c'est probablement quelque chose comme �a (code minimal avec un tableau, � d�bugger):
    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
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
     
    typedef struct _TNODE{
     
    	int elem;
    	struct _TNODE* next;
     
    }TNODE, *PTNODE;
     
    #define MAX_SIZE 10
    int main(int argc, char* argv[])
    {	
    	//tableau de pointeur vers TNODE*
    	PTNODE* nodes = new PTNODE[MAX_SIZE];
     
    	//init elem
    	for(int i = 0; i < MAX_SIZE; i++)
    	{
    		PTNODE pnode = new TNODE;
    		pnode->elem = i;
     
    		nodes[i] = pnode;
    	}
     
    	//init next
    	for(int i = 0; i < MAX_SIZE; i++)
    	{
    		if( i < (MAX_SIZE - 1))
    			nodes[i]->next = nodes[i+1];
    		else
    			nodes[i]->next = nodes[0];
    	}
     
    	//efface 'node' à index 1
    	delete nodes[1];
    #ifndef _DEBUG
    	nodes[1] = NULL;
    #endif
     
    	//node[0]->next pointe maintenant vers node[2]
    	nodes[0]->next = nodes[2];
     
    	//affichage
    	PTNODE current_node = nodes[0];
    	do
    	{
    		printf("[%p] elem: %d ; next: %p\n", current_node, current_node->elem, current_node->next);
    		current_node = current_node->next;
    	}while(current_node != nodes[0]);
     
    	//test sur élément libéré.
    #ifdef _DEBUG
    	printf("[%p] elem: %d ; next: %p\n", nodes[1], nodes[1]->elem, nodes[1]->next);
    #endif
     
    	//libération des pointeurs
    	current_node = nodes[0];
    	do
    	{
    		PTNODE next = current_node->next;
    		delete current_node;
    		current_node = next;
    	}while(current_node != nodes[0]);
     
    	//libère tableau
    	delete[] nodes; 
     
    	return 0;
    }
    Ceci dit, pour une liste circulaire, tu peux tr�s bien te passer du tableau (je dirais m�me que c'est plut�t recommand�).

    Chaque �l�ment pointe vers le suivant ('next'). La disparition (lib�ration) d'un noeud doit alors obligatoirement s'accompagner d'une mise � jour du pointeur 'next' de l'�l�ment qui pointait sur celui lib�r�: comme �a, plus besoin de tableau !

  3. #3
    Membre �prouv�
    Homme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Avril 2007
    Messages
    142
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 43
    Localisation : France, Val de Marne (�le de France)

    Informations professionnelles :
    Activit� : Ing�nieur d�veloppement logiciels
    Secteur : High Tech - �diteur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 142
    Par d�faut
    Merci beaucoup pour ta r�ponse. J'avais compl�tement oubli� de revenir apr�s l'avoir lu et fait qq tests, d�sol�.

    En fait j'avais bien besoin d'un tableau de tNode et non de tNode*, ceci dans un but de performance, et donc pour �viter de faire appel un trop grand nombre de fois � new().
    Mais j'ai contourn� le probl�me d'une autre mani�re.

    Ceci dit, il y a quand m�me qqch qui m'�chappe, tu dis "C'est un comportement normal".

    Hors il me semblait que quand on allouait un tableau d'objets quelconques, avec Obj* tab = new Obj[n], alors il fallait le lib�rer avec delete[], qu'un simple delete ne lib�rait que le 1er �l�ment, ou que le comportement �tait ind�fini (j'ai lu les 2 possibilit�s sur le net).
    Hors ici, il semble que le delete sans les [] lib�re bien tout le tableau, voila pourquoi je pensais que le compilo de visual prenait des libert�s avec la norme.
    Cela reste assez myst�rieux pour moi.

    Encore merci.

+ R�pondre � la discussion
Cette discussion est r�solue.

Discussions similaires

  1. [Migration] Comment réussir VC6.0 >> Visual 2005
    Par ep31 dans le forum EDI/Outils
    R�ponses: 6
    Dernier message: 06/07/2006, 17h21
  2. Visual 2005 & Qt4 Opensource
    Par chkpos dans le forum MFC
    R�ponses: 3
    Dernier message: 08/02/2006, 18h08
  3. OpenMP sous Visual 2005
    Par teddy fredaigues dans le forum MFC
    R�ponses: 6
    Dernier message: 19/01/2006, 14h43
  4. [Visual 2005] Dacris et NETXP sous visual 2005
    Par Dinytro dans le forum Windows Forms
    R�ponses: 5
    Dernier message: 06/09/2005, 12h30

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo