45 votes

Pourquoi dois-je supprimer []?

Disons que j'ai une fonction comme celle-ci:

 int main()
{
    char* str = new char[10];

    for(int i=0;i<5;i++)
    {
        //Do stuff with str
    }

    delete[] str;
    return 0;
}
 
  1. Pourquoi aurais-je besoin de supprimer str si je veux tout de même mettre fin au programme? Cela ne me dérangerait pas si ce souvenir allait dans un pays rempli de licornes si je voulais juste sortir, n'est-ce pas?

  2. Est-ce juste une bonne pratique?

  3. Cela a-t-il des conséquences plus profondes?

77voto

Eric Lippert Points 300275

En fait, si votre question est vraiment "j'ai cette triviale programme, est-il correct que je ne suis pas libre, quelques octets avant de sortir?", la réponse est oui, c'est bien. Sur tout système d'exploitation moderne qui va être très bien. Et le programme est triviale; elle n'est pas comme vous allez le mettre dans un stimulateur cardiaque ou de l'exécution du système de freinage d'une Toyota Camry avec cette chose. Si le seul client, c'est vous, alors la seule personne que vous pouvez éventuellement impact par être négligée, c'est vous.

Le problème vient ensuite, lorsque vous commencez à généraliser non négligeable de cas à partir de la réponse à cette question posée à propos d'un cas trivial.

Donc, nous allons plutôt poser deux questions à propos de certains non négligeable de cas.

J'ai une longue exécution d'un service qui alloue et désalloue la mémoire est un processus complexe, impliquant peut-être plusieurs allocateurs de frapper plusieurs tas. L'arrêt de mon service dans le mode normal, c'est long et compliqué processus qui consiste à s'assurer que extérieure de l'état -- fichiers, bases de données, etc-sont constamment fermées. Dois-je assurer que chaque octet de la mémoire que j'ai alloué est libéré avant que je m'arrête?

Oui, et je vais vous dire pourquoi. Une des pires choses qui puisse arriver à un long service en cours d'exécution est si par hasard des fuites de mémoire. Même de petites fuites peuvent s'ajouter à d'énormes fuites au fil du temps. Une norme technique pour la recherche et la correction de fuites de mémoire est à l'instrument, à la répartition des tas, de sorte que lors de l'arrêt, le temps qu'ils se connectent toutes les ressources qui ont été allouées sans être libérés. Sauf si vous aimez chasser vers le bas beaucoup de faux positifs et de dépenser beaucoup de temps dans le débogueur, toujours libre de votre mémoire , même si cela n'est pas à proprement parler nécessaire.

L'utilisateur est déjà en s'attendant à ce que, l'arrêt du service de down peut prendre des milliards de nanosecondes alors, qui se soucie si vous provoquer un peu de pression supplémentaire sur le virtuel allocateur de s'assurer que tout est nettoyé? C'est le prix à payer pour les gros logiciel compliqué. Et ce n'est pas comme vous êtes d'arrêter le service à tout moment, donc encore une fois, qui se soucie si ses quelques millisecondes plus lente que ce qu'elle pourrait être?

J'ai les même à long exécution d'un service. Si je détecte que l'un de mes internes des structures de données est corrompue, je souhaite "fail fast". Le programme est dans un état indéfini, il est probable qu'il exécute avec des privilèges élevés, et je vais supposer que, si je détecte l'état corrompu, c'est parce que mon service est activement attaqué par des partis hostiles. La chose la plus sûre à faire est d'arrêter immédiatement le service. J'ai plutôt de permettre aux attaquants de refuser le service à la clientèle plutôt que de risquer le service de rester debout et de ne pas compromettre mes utilisateurs de données plus loin. Dans cet arrêt d'urgence scénario dois-je faire en sorte que chaque octet de mémoire je alloué est libéré?

Bien sûr que non. Le système d'exploitation va prendre soin de cela pour vous. Si votre tas est corrompu, les attaquants peuvent en espérant que vous libérer de la mémoire dans le cadre de leur exploitation. Chaque milliseconde compte. Et pourquoi voulez-vous la peine à polir les poignées de porte et nettoyage de la cuisine avant de les déplacer d'une arme nucléaire tactique sur le bâtiment?

Donc la réponse à la question "dois-je libérer de la mémoire avant que mon programme s'arrête?" est: "ça dépend de ce que votre programme n'".

39voto

75inchpianist Points 3154

Oui c'est une bonne pratique. Vous ne devez JAMAIS présumer que votre système d'exploitation s'occupera de la désallocation de votre mémoire. Si vous prenez cette habitude, il vous baisera plus tard.

Pour répondre à votre question, toutefois, à la sortie de l'utilitaire principal, le système d'exploitation libère toute la mémoire détenue par ce processus, ce qui inclut les threads générés ou les variables allouées. Le système d'exploitation se chargera de libérer cette mémoire pour que d'autres puissent l'utiliser.

24voto

Roddy Points 32503

Remarque importante : deletes'libérer de la mémoire est presque juste un effet secondaire. L'important c'est de détruire l'objet. Avec RAII dessins, cela pourrait signifier la fermeture des fichiers, libérant de l'OS gère, la terminaison des threads, ou la suppression des fichiers temporaires.

Certaines de ces actions seraient traitées par le système d'exploitation automatiquement lors de votre processus de sortie, mais pas tous.

Dans votre exemple, il n'y a pas de raison de ne PAS appeler delete. mais il n'y a pas de raison d'appeler à l' new , de sorte que vous pouvez contourner le problème de cette façon.

char str[10];

Ou, vous pouvez contourner le supprimer (et à l'exception problèmes de sécurité liés) à l'aide de pointeurs intelligents...

Donc, en général, vous devriez toujours vous assurer que votre objet est la durée de vie est bien géré.

Mais il n'est pas toujours facile: des Solutions de contournement pour l' initialisation statique afin fiasco signifie souvent que vous n'avez pas d'autre choix que de compter sur le système d'exploitation le nettoyage d'une poignée de singleton de type objets pour vous.

16voto

Ben Jackson Points 28358

Contrairement réponse: Non, c'est une perte de temps. Un programme avec une grande quantité de données allouées aurait à toucher presque chaque page afin de restituer la totalité des attributions de la liste libre. Cette gaspillages de temps CPU, crée une pression sur la mémoire pour inintéressant de données, et peut-être même le processus pour changer l'ordre des pages de retour à partir du disque. Simplement de quitter les communiqués de tous les secours de la mémoire pour le système d'exploitation sans aucune autre action.

(non pas que je suis en désaccord avec les raisons à "Oui", je pense juste qu'il y a des arguments dans les deux sens)

6voto

eandersson Points 8571

Votre système d'exploitation doit prendre soin de la mémoire et la nettoyer lorsque vous quittez votre programme, mais il est généralement recommandé de libérer toute mémoire que vous avez réservée. Personnellement, je pense qu'il est préférable de se mettre dans la bonne mentalité de le faire, car pendant que vous faites des programmes simples, vous êtes probablement en train de le faire pour apprendre.

Quoi qu'il en soit, le seul moyen de garantir la libération de la mémoire est de le faire vous-même.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X