2010-03-18 4 views
1

Est-ce un C++ valide (par exemple, ne pas invoquer UB) et obtient-il ce que je veux sans fuites de mémoire? Valgrinds se plaint de la non-concordance free et delete mais dit "aucune fuite n'est possible" à la fin.new [n] et supprime chaque emplacement avec delete à la place du bloc entier avec delete []

int main() { 
    int* a = new int[5]; 
    for(int i = 0; i < 5; ++i) 
    a[i] = i; 

    for(int i = 0; i < 5; ++i) 
    delete &a[i]; 
} 

La raison pour laquelle je demande: J'ai une classe qui utilise boost::intrusive::list et je new chaque objet qui est ajouté à cette liste. Parfois, je sais combien d'objets je veux ajouter à la liste et je pensais à utiliser new[] pour allouer un morceau et être toujours capable de delete chaque objet à part avec le style Disposer de boost::intrusive.

Répondre

8

Pas moyen. Vous ne pouvez pas appeler delete sur ce qui n'a pas été attribué par new ou vous obtenez une corruption de tas.

Vous voyez, ce tableau créé par new [] n'alloue pas n objets individuels, mais un tableau. Le second objet du tableau se trouve au milieu du bloc d'allocation.

+2

Exactement. Et, quand vous allouer quelque chose avec new (ou new []), il stocke une notation dans une table quelque part que le bloc de mémoire particulier est alloué. Les appels delete (ou delete []) correspondants rechercheront cette notation. –

+0

"Vous ne pouvez pas appeler delete sur ce qui n'a pas été alloué par new ou vous obtenez une corruption de tas." Vous obtenez un accident! –

1

Vous pouvez ajouter un bit afin que chaque objet se souvienne s'il était le premier dans le tableau contigu. Ceci est délicat:

  • totalement incompatible avec delete object syntaxe
  • incompatible avec l'héritage
  • éliminateur appelle à la place destructor explicitement, par exemple object.~ListItem()
  • doit toujours utiliser le tableau operator new[]
  • assurez-vous de disposer des objets en marche arrière ordre, contrairement à votre exemple inclus
  • destructor implémente la propriété réflexive du tableau par son premier élément:

.

ListItem::~ListItem() { 
    if (m_own_my_subarray) { 
     operator delete[](this); // does not invoke any destructor! 
       // "this" must be exactly the result of new[]! 
    } 
} 
+0

Il doit être compatible avec l'héritage car j'utilise intrusive :: list_base_hooks. – pmr

+0

@pmr: 'ListItem' peut être hérité de ** quelque chose ** bien sûr, mais le destructeur doit être comme indiqué. Pour la même raison et dans le même sens, les tableaux d'objets de type C sont incompatibles avec l'héritage. – Potatoswatter

+0

@pmr: Je veux dire que ListItem peut * hériter * de quelque chose comme 'list_base_hook'. Pourriez-vous décrire comment je ne réponds pas à votre question, ou reconnaître avec un upvote? Ce n'est pas une question facile à répondre, et j'ai une bêtise à propos des réponses "c'est impossible" ... – Potatoswatter