tableau de unique_ptr

tableau de unique_ptr

by Jan Jakub Frybes -
Number of replies: 5

Bonjour,

je suis en train de refaire les anciens examens et j'ai une question par rapport au dernier exercice de l'examen de 2015. Il s'agit d'un probleme avec des unique_ptr. L'enonce nous dit que l'erreur que nous affiche le compilateur est « *** Error: free(): invalid size: 0x00007fffb1114130 *** ». Je comprends que l'erreur vient d'un probleme de mauvaise gestion de la memoire (j'ai entendu le terme de double free par rapport a ce probleme, mais je ne sais pas trop ce que c'est). L'erreur a l'air de provenir de la methode ajoute de la classe Client. Neanmoins je ne vois pas trop quelle est l'erreur. Je sais qu'il est possible de resoudre le porbleme en faisant un tableau de pointeurs a la C au lieu de unique_ptr (j'ai verifie avec un compilateur), mais dans le cours il nous est conseille plusieures fois de privilegier les unique_ptr. Comment pourrait on resoudre ce probleme sans passer par les pointeurs a la C? Cela est-il possible et si oui quelle methode privilegier?  

Merci d'avance 

In reply to Jan Jakub Frybes

Re: tableau de unique_ptr

by Fares Ahmed -

Bonjour,

je n'ai pas l'examen en question donc je ne pourrai pas beaucoup vous aider. Ce genre d'erreur apparaît effectivement lors de problèmes lors de la libération de mémoire : typiquement un delete d'un pointeur alloué statiquement ou plusieurs delete sur le même pointeur. Pour résoudre ce problème, inspectez le programme pour un de ces cas-là et enlevez les delete fautifs (surtout dans le cas des unique_ptr vu qu'ils sont libérés automatiquement: pas besoin d'explicitement faire appel à delete).

In reply to Fares Ahmed

Re: tableau de unique_ptr

by Jan Jakub Frybes -

Merci pour la reponse, malheureusement je n'ai toujours pas compris comment on doit faire. En fait il n'y a aucun delete dans tout le programme.

la question est plus generale, j'essaierai de donner un exemple plus clair. 

Il s'agit de creer une collection heterogene d'objets d'un superclasse abstraite A. Ses sous-classes, supposons B et C sont bien definies, toutes les methodes virtuelles pures de A sont redefinies. Ma question est la suivante : On cree une classe D qui doit contenir une collection heterogene d'objets de la classe A, un peu comme la classe Systeme dans le projet. Le tableau doit etre fait avec des pointeurs de ce que j'ai compris, mais est-ce qu'on devrait choisir des pointeurs a la C ou des unique_ptr? Dans le cours il est conseille d'utiliser des unique_ptr mais le probleme (souleve dans l'examen 2016) est que en faisant une methode ajoute qui ajoute un pointeur sur un A a la liste il semble y avoir un souci. Le code de cette methode est 
void ajoute () (A* a) {
liste.push_back(unique_ptr<A>(a));  }

Le probleme survient quand dans la main on essaie de faire 

int main (){

B b (constructeur);

D d ;

D.ajoute(&b);

}

Le programme n'a pas l'air d'aimer le fait d'avoir des unique_ptr et qu'on passe b par reference. En particulier si on cree un pointeur sur b avec un new cad on fait

B* b = new B (constructeur);

D.ajoute(b)

le probleme disparait. Une autre solution est de changer le tableau en un tableu de pointeurs a la C. Alors la premiere methode marche. Finalement ma question est est-ce qu'on peut faire un tableau de unique_ptr sans devoir initialiser l'objet dans la main comme un pointeur avec new? Si oui comment et quelle est la facon preferable entre tableau de pointeurs a la C et tableau de unique_ptr?

Merci d'avance

In reply to Jan Jakub Frybes

Re: tableau de unique_ptr

by Jean-Baptiste Bruno Marie Valentin -

je crois que l'erreur vient du faite que dans le cours du semestre 1 ils disent que pour initialiser un unique_ptr il fallait faire unique_ptr<type> nom(new type(valeur)); 

donc je sais pas si on a le droit de juste faire passer l'adresse comme ca.

après je suis pas sur je fait que suivre le cours. 

In reply to Jan Jakub Frybes

Re: tableau de unique_ptr

by Fares Ahmed -

Tout d'abord attention: l'expression "&b" n'est pas un passage par référence, mais bien un pointeur sur objet de type B.

Ensuite, d'après ce que je vois l'erreur correspond bien exactement au premier cas que j'ai énoncé: un pointeur alloué statiquement libéré à l'aide d'un delete. A noter qu'ici cet appel à delete se fait lors de la destruction de l'unique_ptr associé, ce qui explique pourquoi il n'y a pas de delete "explicite" dans le programme (revoir le cours sur les pointeurs intelligents si nécessaire). Dans ce cas là une solution valable serait effectivement que de créer et passer un "vrai" pointeur à la fonction ajoute() plutôt que l'adresse d'un objet alloué statiquement.

Pour l'utilisation des unique_ptr/pointeurs "à la C" dans des collections hétérogènes, je vous recommande de revoir le cours du 2 avril ainsi que les deux vidéos du MOOC sur les collections hétérogènes (semaine 5) qui devraient pouvoir répondre exhaustivement à vos questions.