Hier soir j'ai eu un "débat" (si on peut appeler ça comme ça), où l'on parlait de l'inutilité de désaoullé la mémoire pour des programmes "courts" (Par "cours" entendez: qui s'exécute en quelques secondes, voire quelques minutes à la limite et qui consomme pas beaucoup de mémoire "Quelques centaines de Mo maximum").
Du coup c'est l'heure des questions !
1) Le coût de delete (ou free peu importe) est t'il réellement notable au point de laisser tout ce qu'on a alloué en plan à la fin du programme ?
2) Est-ce vraiment efficace de laisser le système faire le ménage ou les ressources que va utiliser ce dernier sont aussi, voire plus, importantes que celle nécessaire pour du delete sur tout ce qu'on a alloué ?
Je ne suis pas spécialiste en la matière, mais de ce qu'on m'en a enseigné, la libération de mémoire est certes importante, mais les OS d'aujourd'hui se chargent très bien de nettoyer derrière quand nécessaire. Par soucis de rigueur il vaut mieux prendre l'habitude de toujours libérer la mémoire, surtout en C où, contrairementau C++, il n'y a pas de "garbage collector".
Donc pour un programme très court allouant peu de mémoire, en soi ce n'est pas critique de ne pas la libérer, tant que ça reste à petite dose.
Il est super crade de "tout laisser en plan". Dans ma boîte, celui qui fait ça est passible de la peine de mort.
De plus, tu ne vas rien gagner du tout, car si tu delete toi même, ou si tu laisses la machine faire, le delete sera fait de toute façon, et le temps sera perdu de la même manière.
Ta question est très orientée. Donc oui, si ton programme est tout petit, ne consomme pas trop de mémoire, le système va clean la mémoire à la fin, donc pas de trop de problemes. Et même si c'est le cas, quel est le risque ? D'avoir 10k-100k perdu sur plusieurs Go de mémoire ? Il est clair qu'on s'en fout.
Mais es-tu sur que ton "mauvais" programme ne va pas poser des problèmes que tu n'avais pas prévu ? Si par exemple, tu as une fuite mémoire et que ton programme consomme 2Go de memoire apres quelques minutes ? Ou si tu as des processus morts, qui ne sont pas nettoyé par le système ? Ou des ressources (comme le réseau) qui ne sont pas correctement libérées et qui ralentissent ta connexion ?
Es-tu sur d'avoir suffisamment bien conçu ton programme pour mal faire les choses mais pas trop mal pour eviter les problemes ?
Quel est l'interet de chercher a faire une mauvaise conception mais pas trop mauvaise, plutot que de faire directement une bonne conception ?
Est-ce que tu peux prévoir à la conception de ton programme que tu ne vas pas perdre des heures en debug pour supprimer un problème ?
Quel est l'interet de perdre du temps a faire de la mauvaise gestion manuelle de la mémoire, qui peut potentiellement rendre ton programme tres problematique, plutot que faire directement de la gestion automatique de la mémoire ?
En termes d'apprentissage, tu as l'intention d'apprendre a gerer correctement la memoire quand tu seras sur un projet pro de plusieurs centaines de millier de lignes de code ? Est-ce que ca serait pas une bonne idée de profiter de tes petits projets pas important pour apprendre a programmer comme on ferait dans un projet pro ?
Donc oui, ton système va probablement libérer correctement la mémoire. Mais c'est quand même une erreur de faire cela, en termes de risques potentielles et d'apprentissage. Surtout que faire un code correct ne prend pas plus temps à écrire qu'un code moisi.
Je rajouterai: quid si après un refactoring une partie du programme est extraite pour finir dans un autre programme qui tourne h24, 7j/7? Ou pire dans une bibliothèque qui sera distribuée et utilisée par des "utilisateurs" que l'on ne maîtrise pas ?
Bref, à l'ère du RAII (déjà officiellement là en 98... oui, oui il y a 20 ans!), quel est le problème à bosser proprement?
l'allocation et la libération des ressources a un cout, c'est certain.
Mais ne pas libérer les ressources aura systématiquement un cout encore plus important, ne serait-ce que parce qu'elles ... sont indisponibles pour d'autres choses.
A l'heure actuelle, avec des PC qui ont plus de RAM que ce que l'on trouvait comme disque dur il y a vingt ou trente ans, on pourrait, effectivement, se poser la question de ce que peuvent faire "quelques Mb de perdus".
Tout comme on pourrait se poser la question de savoir à quoi il sert de réfléchir à son algorithme avant de se jeter sur le clavier et de commencer à "vomir du code", vu que l'on peut -- potentiellement -- faire plusieurs milliers d'essais / erreurs par jour;
Mais un fait est toujours le même: si tu prend trois minutes à réfléchir à ton algorithme, si tu "perds" les "quelques cycles d'horloge" nécessaires à la libération d'une ressource, tu vas systématiquement gagner sans doute quelques heures de débugage, ou être sur que cette ressource ne fera pas défaut "au moment le plus critique". Et ca, ca n'a pas de prix
Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
Tant de réponses ! Je vais répondre dans l'ordre pour commencer:
Insonore: Merci pour ta réponse. Effectivement le système récupère la mémoire (Encore heureux), et justement c'était la base de la réflexion. Pour ce qui est de l'histoire de garbage collector, il n'y en a pas en C++ (On ne peut pas comparer stack et GC, c'est trop différent).
Fvirtman: Je suis moi aussi de ce point de vue, et justement je défendais le fait de delete (pas à la main de préférence), car pour moi pendant ou après c'est pareil.
Gbdivers: Tient, j'avais pas pensé à la partie debug, est-ce que ça a une chance de gêner le debugger d'avoir des morceaux de mémoire perdu au milieu de nulle part ?
Lmghs: Oui la partie maintient je l'avais mis en avance, mais c'est sûr que ça rend un code impossible à réutiliser (À moins de refaire ce même tour de passe-passe immonde).
Koala: Oui donc ce n'est pas rentable quoi qu'il arrive, même si du coup c'est pas vraiment des histoires de performance mais plus de maintenance.
Donc on est d'accord, ce n'est pas une bonne idée. Quoi qu'il arrive le ratio avantage/désavantage est trop fort du côté désavantage, car pour "quelques cycles d'horloge", on se met une énorme écharde dans la main.
Et même l'argument "pour quelques cycles d'horloge" est mauvais, car quand tu fermes un programme, l'OS va quand même tout nettoyer, donc si tu en as beaucoup à nettoyer, l'OS va mettre plus de temps à fermer ton programme. Donc que tu libères ou pas avant la fin du programme, je dirais que de toute façon, le temps qu'il soit bien fermé, tu n'auras rien gagné à faire le porc.
Sinon, lmghs a tout dit en une phrase : à l'ère du RAII, normalement, tout se delete tout seul si tu n'utilises pas de pointeurs nus.
Mais faisant moi même aussi pas mal de C, il faut prendre l'habitude de libérer. Pas mal de nos clients sont bien pointilleux sur les désallocations et les memory leak.
Tu devrais amener tes potes qui défendent "la porcherie" ici qu'on en discute.
Je me doute que n'importe qui de sensé préfère un code qui n'a pas des petit trous de partout.
Le plus drôle c'est que celui qui m'a parlé de cette technique douteuse m'a dis que c'était un de ses profs qui lui avait dis ça. Personnellement je me méfie des profs car beaucoup (trop) sont encore à l'âge de pierre, mais bon pour lui c'est un argument qui tient la route. Bref quoi qu'il en soit, rien ne set de créer des conflits inutiles ils se feront lyncher par tout le monde, grand bien leur fasse.
S'il est clair que "ne pas libérer les ressources" sur un petit programme à un impacte négligeable sur le système, le réel impact se situe ailleurs, et il aura de graves conséquences sur le futur: Les mauvaises habitudes.
Celui dont on ne corrige pas les "petites conneries" pendant son apprentissage les reproduira immanquablement plus tard, sur des projets plus importants, ce qui est rapidement chronophage à corriger, et a coup de 500€+ par jour et par personne, ca chiffre aussi très vite.
En soit, on peut effectivement imaginé ce type d'optimisation, mais faut vraiment être super sûr de son coup :
J'ai un calcul très couteux à faire, j'ai besoin de la réponse le plus vite possible (faut donc pas que ce soit un programme qui tourne 3ans, sinon ya de très forte chance que ça consommation mémoire soit grosse au totale au fur et à mesure). Dans le cas où on a une certitude sur la consommation mémoire, on pourrait par exemple imaginer une attaque, qui doit être lancée a un instant précis, une seule fois, et dont le fait qu'elle se finisse à la micro seconde pret peu avoir un impact (dans un cas ou on a pas la possibilité d'ajouter 20€ sur le cout du processeur pour accélérer la chose donc, c'est vraiment dur à imaginer, mais en soit c'est possible).
Dans ce cas on peut décider de delayer la libération de la mémoire à la fin du programme, garder le cout de cette désallocation pour la fin.
Mais même dans ce cas, on peut aussi libérer la mémoire dans le programme, sans laisser l'OS le faire. Delayer la libération de la mémoire c'est fréquent (par exemple un allocateur qui alloue par bloc prédéfinis, un delete ne liberera pas forcément de mémoire).
Donc en soit ca s'imagine comme scénario, mais au final il y a toujours pas de raison particulière de faire un truc aussi sale. Après dans le cas d'un malware qui veut limiter son temps d'exécution, il peut effectivement décider que si il laisse l'OS le faire c'est plus safe, mais dans ces cas là les fuite mémoires sont pas la priorité absolue de toutes facon :p.
Il n'y a pas d'optimisation, si tu ne libères pas l'OS va le faire, plus ou moins bien... et le temps de nettoyage de l'OS n'est pas négligeable, il dépend de la quantité et de la nature des ressources à libérer, donc une optimisation là dessus, c'est totalement crétin, d'abord parce que tu n'as aucune garantie sur le temps que cette libération va prendre, ensuite parce qu'en sortie du programme tu n'es pas sur un chemin critique donc ce n'est pas capital.
Sauf si il s'agit de relancer le programme le plus vite possible, et là il vaut vaut mieux une libération ultra clean qu'un passage au karsher. En plus, il faut faire confiance à l'OS ou au runtime du programme pour le nettoyage, ma vielle expérience, montre que c'est un pari assez risqué, si l'OS ou le runtime n'est pas assez robuste, tu risque de te payer le reset hardware manuel, ou le watchdog (s'il y en a un), en espérant que le bouzin redémarrera correctement...
Bien sûr, les runtime, et OS sont 100% sûrs, c'est pour ça que le "kernel panic" ou le "blue screen of death" sont des pures légendes
@Numenor: si je peux mettre un processeur à 5€ à la place d'un processeur à 20€, je me mets 15€ dans la poche, ou bien je peux vendre mon barda 15€ de moins que mes concurrents. Un design hard, ça coûte un bras, on dimensionne le hard pour le boulôt à faire, et quand on commence à penser en millers de pièces, quelques centîmes par ci par là, font la différence entre un projet rentable et un gouffre financier.
Dans les faits, on sait qu'une allocation(resp une libération) possède un coût en temps et en ressources difficilement quantifiable. La principale idée pour avoir des grosses performances, c'est de faire en sorte de ne pas avoir d'allocation sur un chemin critique d'exécution, ou bien s'il doit y avoir allocation, faire en sorte qu'elles soient les plus rares possibles, pareil pour les libérations. L'idéal, c'est qu'il y ait le moins possible d'allocations/libérations sur le chemin critique. Cela implique de concevoir son programme de telle façon qu'il recyclera ses ressources de la façon la plus optimale possible. Aucune chance que la stratégie optimale consiste à laisser l'OS faire le ménage.
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Recueil de code C et C++ http://fvirtman.free.fr/recueil/index.html
Discord NaN. Mon site.
Recueil de code C et C++ http://fvirtman.free.fr/recueil/index.html