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++

  1. #1
    Membre chevronné
    Avatar de cpcdos
    Homme Profil pro
    Ingé/concepteur chez Capgemini. Alstom APTIS. Concepteur de Felly autonomous vehicle software.
    Inscrit en
    Mai 2010
    Messages
    588
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    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 : 588
    Points : 1 770
    Points
    1 770
    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 chevronné
    Avatar de cpcdos
    Homme Profil pro
    Ingé/concepteur chez Capgemini. Alstom APTIS. Concepteur de Felly autonomous vehicle software.
    Inscrit en
    Mai 2010
    Messages
    588
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    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 : 588
    Points : 1 770
    Points
    1 770
    Billets dans le blog
    1
    Par défaut
    Ah et j'oublie le rendu final :
    Nom : GPP-delete.png
Affichages : 1161
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 éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

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

    Informations forums :
    Inscription : Février 2005
    Messages : 5 073
    Points : 12 119
    Points
    12 119
    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.

  4. #4
    Expert éminent sénior

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

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

    Informations forums :
    Inscription : Juin 2005
    Messages : 2 031
    Points : 11 379
    Points
    11 379
    Billets dans le blog
    10
    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).

  5. #5
    Membre chevronné
    Avatar de cpcdos
    Homme Profil pro
    Ingé/concepteur chez Capgemini. Alstom APTIS. Concepteur de Felly autonomous vehicle software.
    Inscrit en
    Mai 2010
    Messages
    588
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    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 : 588
    Points : 1 770
    Points
    1 770
    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à

  6. #6
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    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.

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

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

    Informations forums :
    Inscription : Octobre 2009
    Messages : 523
    Points : 2 278
    Points
    2 278
    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.
    De retour, plus sportif mais toujours aussi moche.
    _____________
    Pro: Programmation en C/C++ (embarqué ou non)
    Loisir: Programmation en C++11/14/17 avec la STL ou Qt 5

  8. #8
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Citation Envoyé par VivienD Voir le message
    Un petit coup de delete[] test->tata avant de détruire test et on n'en parle plus.
    Alors ça, c'est le pouce rouge instantané.
    Ce n'est pas au propriétaire de test qu'il appartient de détruire test->tata, mais au destructeur de MaClasse!
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  9. #9
    Membre expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    739
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2011
    Messages : 739
    Points : 3 627
    Points
    3 627
    Par défaut
    Citation Envoyé par VivienD Voir le message
    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.
    Être vigilant est trop difficile, et même impossible en C++: chaque ligne peu jetée des exceptions, il faudrait des try/catch a de trop nombreux endroit pour libérer convenablement la mémoire.

    Citation Envoyé par VivienD Voir le message
    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
    C'est faux, il n'y a pas de coût mémoire.

  10. #10
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Alors ça, c'est le pouce rouge instantané.
    Ce n'est pas au propriétaire de test qu'il appartient de détruire test->tata, mais au destructeur de MaClasse!
    La mémoire est allouée en dehors de la classe, je vois pas pourquoi elle devrait être libérée par celle-ci.

    C'est faux, il n'y a pas de coût mémoire.
    Il peut y en avoir un si tu utilises un deleter personnalisé.
    Et dans tous les cas, il y a bien une indirection supplémentaire, donc un possible surcout d'exécution.

    Et le faire aussi si test->tata = new ... échoue. Et peut-être d'autres endroits. Le meilleur moyen de ne pas en oublier est de ne pas s'en occuper, donc unique_ptr et compagnie.
    C'est pas parce que tu n'écris pas de new qu'il n'y en a pas. Que tu échoues un new ou que ce soit make_unique qui échoue en interne, si tu veux l'intercepter il faut le tester. Donc, il faut toujours s'en occuper. Que ce soit via try catch parce que l'allocation lance un bad_alloc ou par simple if parce que ton pointeur finale est null à cause du bad_alloc traité en interne par make_unique.
    Mais bon pratique, si une allocation échoue, sauf cas particulier (parce qu'il y a toujours quelqu'un pour venir te dire "ué mais moi je bosse en hopital, ou sur un lance-missile du rafale et ce que tu dis c'est faux ici"), tu peux laisser ton programme planter et générer un crashdump pour comprendre le souci. Et la plupart du temps ça sera juste que l'utilisateur a plus de ram dispo, et tu peux rien y faire. Sauf qu'en embarqué et autres systèmes spécifiques (donc pas du dév d'applis windows en gros), le système tu le connais, et il n'a pas un nombre d'application lancées aléatoires et quantité de ram indéterminée.
    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.

  11. #11
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,
    Citation Envoyé par VivienD Voir le message
    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.
    Hum... il ne faut pas se contenter d'apprendre à utiliser correctement new et delete... Il faut surtout apprendre à les utiliser de manière opportune; c'est à dire (pour faire simple) quand on n'a pas d'autre choix que d'y avoir recours et, de préférence, en utilisant les fonctionnalités qui nous permettront d'y avoir recours de manière sécurisées (pointeurs intelligents inside)
    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.
    Absolument pas : sizeof(std::unique_ptr<QuelQueSoitLeType) == sizeof(ptr_t)(la taille en mémoire d'un unique_ptr est égal à la taille utilisée par le système pour représenter une adresse mémoire, ni plus, ni moins) et la taille d'un std::array correspond exactement à la taille nécessaire en mémoire pour pouvoir représenter le nombre d'éléments indiqués. Ni plus, ni moins.

    Maintenant, si tu venais à parler de std::shared_ptr, alors, là, oui, effectivement : il y a un léger surcout en mémoire du au fait qu'il faut bien garder une trace du nombre de références vers l'objet pointé qui existent... Mais on est souvent content de payer ce prix lorsqu'il s'agit de s'assurer qu'une ressource mémoire ne sera pas libérée "n'importe quand"
    À 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.
    .
    Ne te tracasse pas : le moment où tu n'auras pas d'autre choix que de t'intéresser à la gestion dynamique de la mémoire viendra toujours bien assez tôt... Toujours trop tôt diront sans doute certains (avec une bonne partie de vérité).

    Car new et delete font en réalité bien plus que "simplement demander/rendre de la mémoire au système" et que la compréhension du mécanisme mis en place par new passe par la compréhension du mécanisme des exceptions et que tout cela nécessite d'avoir un recul important pour comprendre toute l'ampleur des problèmes que cela pose

    Si bien que, contrairement à ce que l'on croit, la gestion dynamique de la mémoire n'est pas une affaire de débutant en C++, mais bel et bien une des notions les plus avancées que l'on pourrait trouver (bien qu'il y ait d'autres notions "encore plus avanceés", mais le problème n'est pas là )
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  12. #12
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Il peut y en avoir un si tu utilises un deleter personnalisé.
    Et dans tous les cas, il y a bien une indirection supplémentaire, donc un possible surcout d'exécution.
    Comme tu dis, il peut y avoir un cout mémoire et il peut y avoir un surcout d'exécution.

    Mais, même un deleter personnalisé ne provoque pas forcément ce genre de surcout car:
    1. Une classe n'a aucune emprunte mémoire si elle ne contient aucune donnée ( 0 sized structure inside)
    2. l'appel d'une fonction inline ne provoque pas forcément une indirection supplémentaire

    Si bien qu'un deleter proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    struct NoDeltion{
        template <typename T>
        void operator()(T * ptr) const noexecept{
            /* just does nothing ... or someone could
             * just call delete ptr 
             */
        }
    };
    ne représentera en réalité abslument aucun surcout, ni en terme de mémoire, ni en terme d'indirection
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  13. #13
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Citation Envoyé par Bousk Voir le message
    La mémoire est allouée en dehors de la classe, je vois pas pourquoi elle devrait être libérée par celle-ci.
    En effet, je n'avais pas vu cette partie... mais la solution serait de déplacer tout cela vers le constructeur, et non l'inverse.

    Ou alors, faire un type Plain Old Data (POD), sans constructeur ni destructeur, façon C. Cela peut se justifier pour un Data Transfer Object (DTO), mais pas pour une classe qui serait censée faire du vrai boulot.
    Et puis pour une telle classe, j'utiliserais le mot-clé struct, même si ça ne change rien au niveau langage (vu que tous les membres sont publics), par convention.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  14. #14
    Membre expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    739
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2011
    Messages : 739
    Points : 3 627
    Points
    3 627
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Il peut y en avoir un si tu utilises un deleter personnalisé.
    C'est très rare. Si le deleter n'a pas de contexte, le coût est nul ([url=http://en.cppreference.com/w/cpp/language/ebo]EBO[/url[). S'il y a contexte, il sera de toute manière quelque part, donc à moins d'être obligé de faire une référence sur un contexte externe le coût sera nul.

    Citation Envoyé par Bousk Voir le message
    Et dans tous les cas, il y a bien une indirection supplémentaire, donc un possible surcout d'exécution.
    Le surcoût introduit par operator-> et operator* ? SI le compilateur n'est pas capable de l'inliné, il y a un problème.


    C'est pas parce que tu n'écris pas de new qu'il n'y en a pas.
    (J'ai supprimé mon paragraphe pour y revenir plus tard pensant que personne n'avait eu le temps de le lire, raté)
    (J'avais lu delete test, ce qui ne rendez pas le propos cohérent)

    Ce que je voulais dire, c'est que des exceptions peuvent être jetées entre le moment du new et celui du delete (pas spécialement un bad_alloc j'entends) et que par conséquent, le delete peut ne pas se faire. Vouloir gérer ou non l'exception n'est pas un problème, l'important étant surtout que ne pas le faire ne fuit pas.

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