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

C++ Discussion :

Supprimer correctement une instance de la mémoire


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert
    Avatar de cpcdos
    Homme Profil pro
    Ingé/concepteur chez Capgemini. Alstom APTIS. Concepteur de Felly autonomous vehicle software.
    Inscrit en
    Mai 2010
    Messages
    589
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingé/concepteur chez Capgemini. Alstom APTIS. Concepteur de Felly autonomous vehicle software.
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 589
    Billets dans le blog
    1
    Par défaut Supprimer correctement une instance de la mémoire
    Bonsoir,
    Depuis quelques heures je me suis penché sur le C++ (avec G++) avec la norme ISO/IEC 14882:2011 donc je suis nouveau dans ce monde, après de longues années passés sur le C (avec GCC), bref, pas grands choses qui changent.
    Je m’intéresse surtout à l'opérateur new (que je j'utilise en C#, PHP, Java..) qui simplifie mon travaille d'allocation / désallocation mémoire dynamique qui me causais beaucoup de problèmes de memory leaks, SIGSEGV en C auparavant par ce que ... je faisais de la m*** voilà c'était pas la joie on n'en parle plus SVP c'est du passé

    Je précise que C++14 ne fonctionne pas sous G++. Et je compile / exécute sous FreeDos/DosBox en DPMI pour l'accès protégé 32bits

    J'ai commencé mon premier code C++11 il y a seulement quelques minutes.
    J'instancie MaClasse avec ce fameux opérateur new (qui doit aussi être un simple malloc) j'assigne mes valeurs, voilà tout est bon tout fonctionne, jusqu’à là OK.

    --> Et là je rencontre de petites difficultés.
    En effet, pour désinstancier ma classe, la vider de ma mémoire, j'utilise la fonction delete. Alors je sais pas comment elle fonctionne, mais j'ai l'impression qu'elle ne fait pas son boulo.
    En C je vide/desalloc tous mes attributs jusqu'à remplir de '0' pour finir par un free via "un semblant d'un destructeur" fait maison. es-ce que delete fait pareil ?

    Après ce fameux delete qui est censé désinstancier MaClasse, que je pensais qu'elle allait la vider de ma mémoire, détruire l'instance, et bien non, ma classe est toujours présente..... , je peux toujours accéder aux attributs, les modifier, les afficher sans avoir un SIGSEGV ou je ne sais quoi.. Bizarre ?

    Pour être plus cohérent, après delete(), je m'attendais à une erreur du style "Impossible d’accéder à l'objet" ou bien "Objet on instancié"...

    Es ce qu'il faut que je fasse pareil qu'en C ? Cet à dire vider les attributs manuellement, et faire mon propre opérateur delete maison qui free() le pointeur ? Ou existe t-il une fonction "spéciale" dans ce C++11 que j'ai pas fais attention ? Les pointeurs restent en mémoire ? Ou ai-je tout simplement fais une faute ?
    Voici mon code :
    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
    #include <stdio.h>
    #include <stdlib.h>
     
    class MaClasse
    {
    	public:
    	int 		toto;
    	int 		titi;
    	unsigned int * 	tata;
     
    	MaClasse()
    	{
    		printf("Constructeur \n");
    	}
    	~MaClasse()
    	{
    		printf("\n---Desctructeur---\n");
    	}
    };
     
    int main()
    {
    	printf("Debut\n");
     
    	// Instance
    	MaClasse * test = new MaClasse;
     
    	// Assignation des valeurs
    	test->tata = new unsigned int[20](); // Creation de 20 tableaux d'unsigned int
    	test->toto = 123;
    	test->titi = 789;
     
    	// Assigner '1234' au nouveau pointeur test->tata
    	for(int b = 0; b < 19; b++) 
    		test->tata[b] = 1234;
     
    	// Afficher les valeurs
    	printf(" Contenu tata:%u\n", (unsigned int) test->tata[9]);
    	printf(" Contenu toto:%u\n", (unsigned int) test->toto);
    	printf(" Contenu titi:%u\n", (unsigned int) test->titi);
     
    	delete test; // deleter l'instance
     
    	// Reafficher les valeurs qui ne doivent plus exister...
    	printf("\n Contenu tata:%u\n", (unsigned int) test->tata[9]);
    	printf(" Contenu toto:%u\n", (unsigned int) test->toto);
    	printf(" Contenu titi:%u\n", (unsigned int) test->titi);
     
    	// Re-assignation de valeurs qui ne doivent non plus exister...
    	printf(" Assignation de valeurs ... \n");
    	test->tata[9] = 5678;
    	test->toto = 2316;
    	test->titi = 2803;
     
    	// Re et reafficher les valeurs qui DOIVENT PAS S'AFFICHER!
    	printf(" Contenu tata:%u\n", (unsigned int) test->tata[9]);
    	printf(" Contenu toto:%u\n", (unsigned int) test->toto);
    	printf(" Contenu titi:%u\n", (unsigned int) test->titi);
     
    	printf("Fin\n");
    	return 0;
    }
    J'essaie de me trouver de bonnes raisons de passer du C au C++11 si c'est largement plus avantageux avant de prendre la décision de réécrire mes projets en C++.

    Merci!
    Sébastien FAVIER
    Felly-software Autonomous vehicle software for everyone.
    co-kernel Cpcdos OSx un noyau 32bits simplifié et complet.. ou presque - Le fofo officiel c'est par ici.
    Les cours sur les systèmes c'est par là

  2. #2
    Membre Expert
    Avatar de cpcdos
    Homme Profil pro
    Ingé/concepteur chez Capgemini. Alstom APTIS. Concepteur de Felly autonomous vehicle software.
    Inscrit en
    Mai 2010
    Messages
    589
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingé/concepteur chez Capgemini. Alstom APTIS. Concepteur de Felly autonomous vehicle software.
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 589
    Billets dans le blog
    1
    Par défaut
    Ah et j'oublie le rendu final :
    Nom : GPP-delete.png
Affichages : 1311
Taille : 4,5 Ko
    Sébastien FAVIER
    Felly-software Autonomous vehicle software for everyone.
    co-kernel Cpcdos OSx un noyau 32bits simplifié et complet.. ou presque - Le fofo officiel c'est par ici.
    Les cours sur les systèmes c'est par là

  3. #3
    Expert confirmé

    Avatar de dragonjoker59
    Homme Profil pro
    Software Developer
    Inscrit en
    Juin 2005
    Messages
    2 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Software Developer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 2 033
    Billets dans le blog
    12
    Par défaut
    Salut!

    Tu ne fais pas du C++11, mais du C++98.
    En C++11, on n'utilise les pointeurs nus, new et delete que si on n'a pas le choix, sinon on utilise std::unique_ptr, std::shared_ptr...
    Sinon, delete ne met pas ta mémoire à 0 (pas plus que free(), d'ailleurs), il rend juste la mémoire au système, qui pourra ensuite la réutiliser pour de futures allocations.
    Il n'est donc pas étonnant que dans ton programme tu puisses toujours accéder à ton objet (même si ça relève du comportement indéfini) : tu ne réalloues rien derrière, donc la mémoire n'est pas modifiée et est restée dans l'état où tu l'as laissée.
    Pour les modifications sur le pointeur deleted je suis surpris, mais on reste dans le domaine du comportement indéfini, donc il est possible que tu aies d'autres résultats avec d'autres compilateurs/systèmes.
    Si vous ne trouvez plus rien, cherchez autre chose...

    Vous trouverez ici des tutoriels OpenGL moderne.
    Mon moteur 3D: Castor 3D, presque utilisable (venez participer, il y a de la place)!
    Un projet qui ne sert à rien, mais qu'il est joli (des fois) : ProceduralGenerator (Génération procédurale d'images, et post-processing).

  4. #4
    Membre Expert
    Avatar de cpcdos
    Homme Profil pro
    Ingé/concepteur chez Capgemini. Alstom APTIS. Concepteur de Felly autonomous vehicle software.
    Inscrit en
    Mai 2010
    Messages
    589
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingé/concepteur chez Capgemini. Alstom APTIS. Concepteur de Felly autonomous vehicle software.
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 589
    Billets dans le blog
    1
    Par défaut
    Merci à vous deux pour vos explications et merci à vous @bacelar pour avoir pris votre temps de rédiger votre réponse, complète et correcte c'est celle que j'attendais!

    C'est purement psychologique de vouloir vite tester si ça marche avant de commencer officiellement et effectivement mes réflexes du C font pas du bon ménage

    Je vais méditer sur vos réponse et essayer d'approfondir mes connaissances C++11 avant de me lancer trop vite, je vous tiens au courant ici si j'ai d'autres questions

    Merci!
    Bonne soirée
    Sébastien FAVIER
    Felly-software Autonomous vehicle software for everyone.
    co-kernel Cpcdos OSx un noyau 32bits simplifié et complet.. ou presque - Le fofo officiel c'est par ici.
    Les cours sur les systèmes c'est par là

  5. #5
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    Je n'ai pas lu les réponses ci-dessus, donc y'a surement de la redite, mais
    J'instancie MaClasse avec ce fameux opérateur new (qui doit aussi être un simple malloc) j'assigne mes valeurs, voilà tout est bon tout fonctionne, jusqu’à là OK.
    oui new alloue la mémoire (équivalent du malloc) et appelle le constructeur

    En effet, pour désinstancier ma classe, la vider de ma mémoire, j'utilise la fonction delete. Alors je sais pas comment elle fonctionne, mais j'ai l'impression qu'elle ne fait pas son boulo.
    En C je vide/desalloc tous mes attributs jusqu'à remplir de '0' pour finir par un free via "un semblant d'un destructeur" fait maison. es-ce que delete fait pareil ?
    delete appelle le destructeur puis libère la mémoire allouée
    "remplir de 0" ne sert strictement à rien, pas plus en C qu'en C++

    et ce sont des opérateurs, donc tu peux les surcharger

    Après ce fameux delete qui est censé désinstancier MaClasse, que je pensais qu'elle allait la vider de ma mémoire, détruire l'instance, et bien non, ma classe est toujours présente..... , je peux toujours accéder aux attributs, les modifier, les afficher sans avoir un SIGSEGV ou je ne sais quoi.. Bizarre ?
    rien de bizarre, ça tombe sous le coup du cas indéterminé
    ton pointeur pointe toujours vers quelque chose, appeler une variable n'est qu'un offset depuis ce quelque chose, tu peux toujours y accéder en lecture, la mémoire disparait pas de ton pc, en écriture tu pourras crasher, ou pas, à fortiori en debug où le debugger assiste beaucoup pour éviter que ça arrive
    et tu as une fuite sur ton tata
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  6. #6
    Membre éclairé
    Avatar de VivienD
    Homme Profil pro
    Développeur logiciel
    Inscrit en
    Octobre 2009
    Messages
    523
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Développeur logiciel
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Octobre 2009
    Messages : 523
    Par défaut
    Bonjour,

    Il est vrai qu'utiliser des pointeurs intelligents et des classes-conteneurs facilite grandement la vie. Toutefois, apprendre à s'amuser avec les opérateurs new, new[], delete et delete[] peut toujours servir et oblige à être vigilant en matière de l'allocation et de libération de la mémoire. Par ailleurs, l'aisance offerte par les classes comme std::unique_ptr et std::array a un coût: ca demande plus de place en mémoire, chose qui peut s'avérer critique lorsque l'on programme un système embarqué ou une application qui doit déjà gérer une grande quantité de données, comme les serveurs notamment.
    À mon avis, tu devrais apprendre aussi bien à utiliser les opérateurs new, new[], delete et delete[] que les classes pour les pointeurs intelligents, comme std::unique_ptr, et les conteneurs, comme std::array et std::vector.

    Citation Envoyé par Bousk Voir le message
    [...]
    et tu as une fuite sur ton tata
    Je confirme. Un petit coup de delete[] test->tata avant de détruire test et on n'en parle plus.

  7. #7
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 489
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 489
    Par défaut
    Je ne sais pas sur quel support de cours tu apprends le C++11, mais si tu en es au mot clé new après quelques minutes, c'est qu'il y a un très gros problème dans ton cours.

    En C++11, le "new" est d'une utilisation exceptionnelle.
    On n'a quasiment plus besoin de faire des new (autre qu'avec des std::unique_ptr, si on utilise C++11 et pas C++14).

    Vous voulez garder vos bons vieux réflexes du C, mais en C++, ces réflexes sont contre-productifs.

    En C++, il y a les exceptions, c'est pour cela qu'on appelle quasiment jamais l'équivalent du free C, le delete C++. On utilise des capsules RAII qui se chargent de faire le ménage de manière fiable.

    En C++, on n'utilise plus non plus les tableaux à la C, mais des classes comme std::array<T> ou std::vector<T>.

    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
    class MaClasse
    {
    	public:
    	int 		toto;
    	int 		titi;
    	std::array<int,20> 	tata;
     
    	MaClasse()
    	{
    		printf("Constructeur \n");
    	}
    	~MaClasse()
    	{
    		printf("\n---Desctructeur---\n");
    	}
    };
    Je vais donc donner des détails sur les mécanismes que vous utilisez, pour assouvir votre curiosité de programmeur C, mais il faudra penser à ne pas s'en servir dans du vrai code C++.

    J'instancie MaClasse avec ce fameux opérateur new (qui doit aussi être un simple malloc) j'assigne mes valeurs, voilà tout est bon tout fonctionne, jusqu’à là OK.
    Oui, "new" est l'équivalent du "malloc + appel du code du constructeur" en C.
    Mais comme le malloc en C, cela fait une allocation dans le tas et pas dans la pile.
    Ici, l'allocation dans le tas ne se justifie pas et donc la déclaration d'une simple variable locale serait bien plus pertinente.
    Si l'allocation dans le tas est nécessaire, il faut faire une analyse de qui est responsable de la destruction de l'objet et utiliser les pointeurs intelligents pour qu'une capsule RAII se charge de la libération automatique de l'objet.

    En C je vide/desalloc tous mes attributs jusqu'à remplir de '0' pour finir par un free via "un semblant d'un destructeur" fait maison. es-ce que delete fait pareil ?
    "delete" peut être vu comme "appel du destructeur de la classe puis de free sur la mémoire"
    Mais attention au fait que "delete" et "delete []" sont différent car le second est utilisé pour détruire un tableau d'objet, comme celui que vous créez ligne 29 de votre code.
    Pour désallouer ce tableau, c'est "delete []" qu'il faut appeler et pas "delete".
    Comme je vous l'ai déjà indiqué, on n'utilise pas de pointeur en C++, donc, avec un std::array en champ à la place d'un pointeur sur tableau, pas besoin d'appel explicite au destructeur du champ, c'est automatique.
    Vous pouvez faire en sorte de mettre tous les champs à 0 dans le destructeur de l'objet, mais c'est vraiment inutile.
    delete, après l'appel du destructeur, fait comme free, il demande à la C-Runtime de rendre la zone mémoire disponible pour des demandes de mémoire ultérieure, pas besoin de tout mettre à 0.

    Après ce fameux delete qui est censé désinstancier MaClasse, que je pensais qu'elle allait la vider de ma mémoire, détruire l'instance,
    Oui, l'instance est détruite car son destructeur a été appelé et la mémoire qu'il occupe/occupait est disponible pour les prochaines demande d'allocation dans le tas.

    et bien non, ma classe est toujours présente.....
    Si, vous ne voyez que son empreinte, qui s'effacera avec les prochaines allocations mémoires.

    les afficher sans avoir un SIGSEGV ou je ne sais quoi.. Bizarre ?
    SIGSEGV ne se déclenche que si la mémoire n'a pas été mappée dans l'espace d'adressage du processus.
    Si la mémoire a déjà été mappée mais qu'elle est libre pour des allocations mémoire, point de SIGSEGV/

    Es ce qu'il faut que je fasse pareil qu'en C ? Cet à dire vider les attributs manuellement, et faire mon opérateur delete qui free() le pointeur ?
    Non, car vous n'aurez pas à utiliser de pointeur, mais, au pire, à utiliser des pointeurs intelligents.

    Ou existe t-il une fonction "spéciale" dans ce C++11 que j'ai pas fais attention ? Ou ai-je tout simplement fais une faute ?
    Il faut utiliser les bonnes pratiques C++, et non celles du C, donc pas de pointeur et utilisation des capsule RAII.

    J'essaie de me trouver des bonnes raison de passer du C au C++11
    Une fois quelques principes maitrisés, le C++11 est bien plus simple que le C.
    Mais apprendre le C puis le C++, c'est un peu le trajet de la mort, désapprendre plein de mauvais reflex.

Discussions similaires

  1. supprimer une instance SQL server
    Par PickEpique dans le forum MS SQL Server
    Réponses: 0
    Dernier message: 01/04/2010, 21h31
  2. [POO] supprimer une instance
    Par Sh4dow49 dans le forum Langage
    Réponses: 3
    Dernier message: 20/09/2008, 16h53
  3. Détruire correctement une instance
    Par Immobilis dans le forum C#
    Réponses: 8
    Dernier message: 20/06/2008, 17h46
  4. Supprimer une liste de la mémoire?
    Par mbk-w dans le forum ASP
    Réponses: 2
    Dernier message: 11/04/2006, 13h14
  5. Réponses: 4
    Dernier message: 08/02/2006, 16h14

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