2010-10-31 7 views
1

TL; DRSuppression de tableau personnalisé provoque Heap erreur

accidents Boost-test-cadre sans erreur donnée en passant tous les tests et fuite toute la mémoire.

Le test échoue plusieurs fois avec les implémentations de destructeur mentionnées. Effacer la fonction renvoie également une erreur de tas.

Que faisons-nous de mal avec le dtor?

TL; DR

Ceci est appartenant à un devoir à la maison de l'université, et la solution de mon ami audit problème. Afin de mieux connaître les pointeurs de style C et un style de programmation plus bas niveau, nous devions implémenter notre propre tableau dynamique.

Son affectation est complète et complètement fonctionnelle selon le cadre de test Boost-900 de notre enseignant. Le seul problème est le crash (ou erreur de tas, car aucun vrai message d'erreur n'apparaît) quand les tests quittent, ou un dtor implémenté est appelé. Son tableau dynamique utilise trois pointeurs: pFirst, pLast and pEnd, pointant sur le premier élément du tableau, sur le dernier élément du tableau et sur le dernier élément non encore attribué dans le tableau. Son programme est passé tant qu'il n'a pas essayé de supprimer des pointeurs. C'est une mauvaise idée, mais bon, ça lui a permis de passer la mission. Pour l'instant.

Mon ami a essayé plusieurs fois d'implémenter un destructeur, mais ils provoquent tous deux des erreurs de tas et provoquent l'échec de l'infrastructure de test.

// Teacher's recommended dtor. 
Field::~Field() 
{ 
    for(int i(0); i != this->size(); ++i) 
     (pFirst+i)->~T(); 
    delete pFirst; 
    pFirst = pLast = pEnd = NULL; 
} 

et

// My recommendation to friend. 
Field::~Field() 
{ 
    delete[] pFirst; 
    pFirst = pLast = pEnd = NULL; 
} 

deux accident avec la même erreur de tas.

Assertion failed: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) 

Une chaîne typique de tests ressemble:

BOOST_AUTO_TEST_CASE(TEST_clear) 
{ 
    Field f(3, 4.0f); 
    f.clear(); // Error here IF we use delete in the clear method. 
    BOOST_CHECK(f.size()==0); 
    BOOST_CHECK(f.capacity()==4); 
} // Error here; during destruction IF we have implemented the dtor. 

La méthode claire émet la même erreur quand nous essayons de remplacer le tableau, donc nous avons juste:

void Field::clear() 
{ 
    size_t capa = capacity(); 
    T *temp =pFirst; 
    pFirst = new T[capa]; 
    pLast = pFirst; 
    pEnd = pFirst+capa; 
} 

Qu'est-ce que est-ce que nous faisons mal avec le dtor, clair et en général en traitant de la suppression des pointeurs?

+0

@Pointy: Une erreur qu'il a corrigé maintenant: P – IAE

Répondre

3

Assertion failed: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) indique une corruption du tas. Habituellement, cela arrive quand vous écrivez après la fin de la mémoire allouée. Je vois le problème suivant dans votre code: dans Field::clear vous stockez le pointeur sur la mémoire allouée dans pFirst et immédiatement remplacez-le par pLast. Je pense que vous devriez le changer en pLast = pFirst;.

Le cours recommandé par l'enseignant n'a aucun sens pour moi. Si vous allouez avec new[] puis désaffectez avec delete[], n'appelez pas chaque destructeur séparément et utilisez delete.

+0

Pour clarifier, vous voulez toujours appeler la suppression sur chaque objet, non? Je suis d'accord avec l'étrangeté d'appeler manuellement le destructeur sur chaque objet. – MintyAnt

+0

@MintyAnt: Non. Puisque 'new T []' est utilisé pour allouer un tableau, 'delete []' devrait être utilisé pour libérer le tableau entier. Appeler 'delete' sur chaque objet serait une erreur. – vitaut

2

Si pFirst pointe vers le premier élément du tableau, alors votre "enseignant recommandé" est erroné. Vous devez indiquer delete[] pFirst pour libérer le tableau.

Cependant, de nombreux problèmes peuvent être à l'origine de cette situation, tels que la corruption du tas causée par une autre fonction. Essayez d'exécuter ceci dans un programme de vérification de corruption de mémoire, tel que Valgrind, pour voir si vous débordez votre mémoire tampon.

Questions connexes