Question

Ignorer le style et la conception de la programmation est-il "sûr"? appeler delete sur une variable allouée sur la pile?

Par exemple:

   int nAmount;
   delete &nAmount;

ou

class sample
{
public:
    sample();
    ~sample() { delete &nAmount;}
    int nAmount;
}
Était-ce utile?

La solution

Non , ce n'est pas safe to call delete sur une variable affectée à une pile. Vous ne devez appeler delete que sur les éléments créés par new .

  • Pour chaque malloc ou calloc , il devrait y avoir exactement un libre .
  • Pour chaque nouveau , il devrait y avoir exactement un supprimer .
  • Pour chaque nouveau [] , il devrait y avoir exactement un supprimer [] .
  • Pour chaque allocation de pile, il ne doit y avoir aucune libération ou suppression explicite. Le destructeur est appelé automatiquement, le cas échéant.

En général, vous ne pouvez pas associer ces éléments, par exemple. pas de free -ing ou supprimer [] -ing un objet new . Cela entraîne un comportement indéfini.

Autres conseils

Eh bien, essayons:

jeremy@jeremy-desktop:~$ echo 'main() { int a; delete &a; }' > test.cpp
jeremy@jeremy-desktop:~$ g++ -o test test.cpp
jeremy@jeremy-desktop:~$ ./test
Segmentation fault

Donc, apparemment, ce n'est pas sûr du tout.

N'oubliez pas que lorsque vous allouez un bloc de mémoire à l'aide de new (ou de malloc, par ailleurs), le bloc de mémoire réellement alloué sera plus volumineux que ce que vous avez demandé. Le bloc de mémoire contiendra également des informations de comptabilité de sorte que lorsque vous libérez le bloc, il peut facilement être remis dans le pool libre et éventuellement être fusionné avec des blocs libres adjacents.

Lorsque vous essayez de libérer de la mémoire que vous n'avez pas reçue de nouveau, ces informations de comptabilité ne seront pas là, mais le système agira comme si c'était le cas et les résultats seraient imprévisibles (généralement mauvais).

Oui, il s'agit d'un comportement non défini: transmettre à delete tout ce qui ne vient pas de new est UB:

  

Standard C ++, section 3.7.3.2.3:   La valeur du premier argument fourni à l'une des fonctions de désallocation fournies dans la bibliothèque standard peut être une valeur de pointeur null ; Si tel est le cas, et si la fonction de désallocation est fournie dans la bibliothèque standard, l'appel de la fonction de désallocation est sans effet. Sinon, la valeur fournie à l'opérateur delete (void *) dans la bibliothèque standard doit être l'une des valeurs renvoyées par un précédent appel de l'un des opérateurs new (std :: size_t) ou opérateur new (std :: size_t, const std :: nothrow_t & amp;) dans la bibliothèque standard.

Les conséquences d’un comportement indéfini sont, bien, indéfinies. "Rien ne se passe" est une conséquence aussi valable que toute autre chose. Cependant, il est généralement "rien ne se passe tout de suite": le désallocation d'un bloc de mémoire non valide peut avoir des conséquences graves sur les prochains appels à l'allocateur.

Après avoir joué un peu avec g ++ 4.4 dans Windows, j'ai obtenu des résultats très intéressants:

  1. appeler supprimer sur une variable de pile ne semble rien faire. Aucune erreur ne se produit, mais je peux accéder à la variable sans problème après la suppression.

  2. Le fait d'avoir une classe avec une méthode avec delete this supprime avec succès l'objet s'il est alloué dans le tas, mais pas s'il est alloué dans la pile (s'il est dans la pile , rien ne se passe).

Personne ne peut savoir ce qui se passe. Cela appelle un comportement indéfini, donc tout peut littéralement arriver. Ne faites pas cela.

Non, La mémoire allouée à l'aide de new doit être supprimée à l'aide de l'opérateur delete et que alloué en utilisant malloc devrait être supprimé en utilisant free. Et pas besoin de désallouer les variables qui sont allouées sur la pile.

Un ange perd ses ailes ... Vous ne pouvez appeler delete que sur un pointeur auquel est attribué new , sinon vous obtenez un comportement indéfini.

ici, la mémoire est allouée en utilisant la pile, donc inutile de la supprimer de manière externe, mais si vous avez allcoted dynamiquement

aime int * a = new int ()

alors vous devez supprimer a et non supprimer & a (un lui-même est un pointeur), car la mémoire est allouée à partir de la mémoire libre.

Vous avez déjà répondu à la question vous-même. delete ne doit être utilisé que pour les pointeurs choisis via new . Faire autre chose est un comportement simple et indéfini.

Par conséquent, rien ne dit vraiment ce qui se passe, que ce soit que le code fonctionne correctement, en passant par le plantage ou l'effacement de votre disque dur est un résultat valable. Alors s'il vous plaît, ne faites jamais cela .

C'est UB parce que vous ne devez pas appeler delete sur un élément qui n'a pas été alloué dynamiquement avec new. C'est aussi simple que cela.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top