OVH Cloud OVH Cloud

Problème de pointeur

12 réponses
Avatar
Michael
Bonjour à tous,

voici mon problème.

J'ai les classes (simplifiées) suivantes:

//----------------------------------------------------------------------
class DS_CrossBar_Pin
{
public:
CrossBar_AV AV;
AnsiString type_connecteur;
long num_pin;
CrossBar_IO IO;

__fastcall DS_CrossBar_Pin();
};

//-----------------------------------------------------------------------
class DS_CrossBar_Input_Pin : public DS_CrossBar_Pin
{
public:
DS_CrossBar_Input_Pin *related_in;

__fastcall DS_CrossBar_Input_Pin();
};

//-----------------------------------------------------------------------
class DS_CrossBar_Output_Pin : public DS_CrossBar_Pin
{
private:
std::vector<DS_CrossBar_Input_Pin *> routing_list;

CrossBar_IO IO;
public:
DS_CrossBar_Input_Pin *routed_in;
DS_CrossBar_Output_Pin *related_out;

__fastcall DS_CrossBar_Output_Pin();
void __fastcall Add_Input_Pin_To_Routing_List
(DS_CrossBar_Input_Pin * pin);
void __fastcall Get_Routing_List(std::vector
<DS_CrossBar_Input_Pin *> & vector);
};

//-----------------------------------------------------------------------
class DS_CrossBar_Infos
{
public:
std::vector<DS_CrossBar_Output_Pin> output_pins;
std::vector<DS_CrossBar_Input_Pin> input_pins;

__fastcall DS_CrossBar_Infos();
__fastcall ~DS_CrossBar_Infos();

void __fastcall Get_Pins();
void __fastcall Get_Relations_Pins();
};

//----------------------------------------------------------------------
Dans DS_CrossBar_Infos::Get_Pins() je remplis les vecteurs output_pins et
input_pins à coups de push_back:

output_pins.push_back(DS_CrossBar_Output_Pin(//...))
input_pins.push_back(DS_CrossBar_Input_Pin(//...))

Ensuite dans la fonction DS_CrossBar_Infos::Get_Relations_Pins() je
renseigne les membres *related_in, *routed_in...

Pour cela, je fais comme suit:

for (std::vector<DS_CrossBar_Input_Pin>::iterator input_pin =
input_pins.begin(); input_pin != input_pins.end(); ++input_pin)
{
//blabla
std::vector<DS_CrossBar_Input_Pin>::iterator ite = std::find
(input_pins.begin(),input_pins.end(),lRelated);
if (ite != input_pins.end())
input_pin->related_in = ite;
}

Comme vous le voyez j'attribue l'iterateur au pointeur related_in...
Ca compile, mais à l'execution j'ai une erreur...

J'imagine que ce n'est pas la bonne affectation, mais je ne vois pas
comment faire...

J'ai essayé d'enlever les pointeurs, mais ça compile plus pour la classe:

//-----------------------------------------------------------------------
class DS_CrossBar_Input_Pin : public DS_CrossBar_Pin
{
public:
DS_CrossBar_Input_Pin related_in; //ici

__fastcall DS_CrossBar_Input_Pin();
};

Est-ce une bonne idée de passer par des pointeurs? Sinon quelles
solutions s'offrent à moi?

Merci d'avance!

2 réponses

1 2
Avatar
Jean-Marc Bourguet
Michael writes:

Mais dans ce cas est-ce que toutes les libérations de mémoire se
feront correctement?


Je n'ai pas lu toute la discussion, mais tu ne fournis pas les
elements necessaires pour repondre.

Les pointeurs intelligents ne sont qu'un moyen d'implementer une
polique de gestion de la memoire. Il faut decider de la polique
d'abord, puis choisir le type de pointeur adequat.

La chose a regarder est quels sont les pointeurs qui peuvent maintenir
l'objet en vie.

Un des problemes supplementaire avec l'utilisation du comptage de
reference est la gestion des cycles. S'il y en a, il faut les casser
a la main car sinon la memoire ne sera jamais liberee.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Avatar
Patrick Mézard
Michael wrote:
Pour m'expliquer autrement, j'ai toujours les classes:

struct A
{
A* related_in;
};

struct B
{
A* routed_in;
B* related_out;

std::vector<A*> r_list;
};

J'ai deux vecteurs:

std::vector<boost::shared_ptr<A> > vect_A;
std::vector<boost::shared_ptr<B> > vect_B;

Maintenant je dois faire pointer A::*related_in vers une instance de A de
vect_A. Seulement maintenant vect_A contient un shared_ptr<A>.

Question:

je laisse tel quel et je fais par exemple:

a.related_in = vect_B.begin().get();


a.related_in = vect_B.begin()->get();


ou bien alors:

struct A
{
boost::shared_ptr<A> related_in;
};

et ensuite
a.related_in = vect_B.begin();


a.related_in = *vect_B.begin();

Mais dans ce cas suis-je sûr que related_in pointe bien vers l'instance de
A voulue, et suis-je sûr que la libération de la mémoire est complète?


Ca dépend...
Les boost::shared_ptr sont des pointeurs intelligents à comptage de
références. Ca signifie que l'objet pointé n'est détruit que lorsque la
dernière instance de shared_ptr le référençant disparait.

Maintenant, pour reprendre les termes de Jean-Marc, il faut définir une
politique de gestion de mémoire. S'il est garanti que "vect_A", "vect_B"
et les pointeurs qu'ils contiennent ne sont plus modifiés une fois
remplis, et que cela tient durant toutes le manipulation d'instances de
A et B, alors tu peux te contenter de récupérer les pointeurs via get().
Il n'arrivera en effet jamais qu'un élément pointé par "related_in" ou
un autre pointeur "nu" soit détruit à son insu.

Si "vect_A", "vect_B" ou leur contenu peuvent changer, en effaçant un
élément par exemple, alors tout se complique. Ca ne signifie pas pour
autant que tu doives remplacer tes pointeurs "nus" par des shared_ptr,
plutôt que tu doives conserver le fameux invariant <"related_in" est
NULL ou pointe sur une instance existante>, le shared_ptr n'étant qu'un
moyen pas forcément très *logique" de conserver cet invariant (de fait
ils empêchent la destruction de l'objet tant qu'ils le référencent). Ce
qui est logique, c'est que lorsque tu enlèves un élément de "vect_A", ça
signifie quelque part que tu le retires de ton graphe, donc *au
préalable tu dois défaire tous les liens le référençant au sein de ton
graphe*. Si tu fais ça, en mettant tous le pointeurs le référençant à
NULL par exemple, alors tes invariants seront valides une fois l'objet
détruit. Ce qui arrivera une fois que l'instance du shared_ptr de
"vect_A" aura disparue.

Note que si tu prends soin d'enlever toutes le références à l'objet dans
ton graphe avant de le retirer de "vect_A", alors les cycles qui
pourraient exister sont naturellement brisés. Mettre des shared_ptr à la
place de pointeurs nus fonctionneraient sans problèmes mais ce serait
complètement inutile.

Patrick Mézard

1 2