C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Comment bien désallouer un vector<string> reservé ?
Goto page 1, 2  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (French)
View previous topic :: View next topic  
Author Message
Alex
Guest





PostPosted: Mon Feb 07, 2005 10:16 pm    Post subject: Comment bien désallouer un vector<string> reservé ? Reply with quote



Bonjour,
Dans mon programme, j'ai besoin d'avoir un espace contigue de string et pour
cela je fais :

std::vector<string> MesStrings;
MesString.reserve(1000); // <= Si je reserve pas, l'espace n'est
pas contigue et a chaque ajout il me change les adresses
// et dans mon prog il
me faut des adresses qui ne changent pas a chaque ajout

// J'ajoute kk string
for (int i=0;i<100;i++)
{
string temp = "toto";
MesString.push-back(temp);
}

Ensuite, pour désallouer l'espace je fais :
MesString.clear();

Mon compilateur (vc++) me dit que j'ai des fuites. J'ai noté que si je ne
reserve pas d'espace au debut, je n'ai pas ces memory-leak.

Quelqu'un peut-il m'expliquer le pourquoi du comment ???
Merci !

--
---------------------------------------------------------------------------
Envie de déco ? http://www.decoetalage.net


Back to top
Alex
Guest





PostPosted: Mon Feb 07, 2005 10:26 pm    Post subject: Re: Comment bien désallouer un vector<string> reservé ? Reply with quote



Hmm autant pour moi, meme sans .reserve() ca me met des leak.

"Alex" <rdpdo2002 (AT) yahoo (DOT) fr> a écrit dans le message de news:
4207e8c6$0$25782$8fcfb975 (AT) news (DOT) wanadoo.fr...
Quote:
Bonjour,
Dans mon programme, j'ai besoin d'avoir un espace contigue de string et
pour cela je fais :

std::vector<string> MesStrings;
MesString.reserve(1000); // <= Si je reserve pas, l'espace
n'est pas contigue et a chaque ajout il me change les adresses
// et dans mon prog il
me faut des adresses qui ne changent pas a chaque ajout

// J'ajoute kk string
for (int i=0;i<100;i++)
{
string temp = "toto";
MesString.push-back(temp);
}

Ensuite, pour désallouer l'espace je fais :
MesString.clear();

Mon compilateur (vc++) me dit que j'ai des fuites. J'ai noté que si je ne
reserve pas d'espace au debut, je n'ai pas ces memory-leak.

Quelqu'un peut-il m'expliquer le pourquoi du comment ???
Merci !

--
---------------------------------------------------------------------------
Envie de déco ? http://www.decoetalage.net




Back to top
David
Guest





PostPosted: Mon Feb 07, 2005 10:30 pm    Post subject: Re: Comment bien désallouer un vector<string> reservé ? Reply with quote



Bonsoir,

Quote:
Bonjour,
Dans mon programme, j'ai besoin d'avoir un espace contigue de string et pour
cela je fais :

juste par curiosité, on peut savoir pourquoi ?
ça m'intrigue.

David.

Back to top
Alex
Guest





PostPosted: Mon Feb 07, 2005 11:22 pm    Post subject: Re: Comment bien désallouer un vector<string> reservé ? Reply with quote

Alex wrote:

Quote:
Bonjour,
Dans mon programme, j'ai besoin d'avoir un espace contigue de string et
pour cela je fais :

std::vector<string> MesStrings;
MesString.reserve(1000); // <= Si je reserve pas, l'espace
n'est pas contigue et a chaque ajout il me change les adresses
// et dans mon prog il
me faut des adresses qui ne changent pas a chaque ajout

Logiquement ça doit pas être à chaque coup. Quand il ne suffit pas, il doit
te réserver une vingtaine d'éléments d'un coup pour laisser la marge.

En fait, ce que tu appelles l'espace contiguë n'est que l'espace pour
stocker la classe de string, tu vois ce que je vais dire ?
A l'intérieur de celle-ci il y a cependant un ou plusieurs new pour alouer
les tableaux de char où la classe string va stocker ces caractères. Et ça
c'est ton système qui va le faire sur le Heap, quoique si tu développes ton
propre gestionnaire de mémoire qui va placer toutes tes chaînes dans
l'espace contiguë...

Les fuites sont peut-être dues à "un bug" dans STL. C'est que reserve 1000
fait marcher 1000 fois le constructeur de string, qui fait new. Derrière à
la destruction de ton vector il parcours pour détruire que les éléments
vraiment affectés ensuite.

si tu remplis MesStrings jusqu'à 100, le destructor fait un truc d'en genre

for(int iElem = 0; iElem < m_nSize; iElem++)
{
delete ...[iElem]; // un tableau où j'sais pas comment il stocke ses trucs
}

où m_nSize égale à la taille réelle du vecteur et non de la mémoire réservée


Back to top
Loïc Joly
Guest





PostPosted: Mon Feb 07, 2005 11:47 pm    Post subject: Re: Comment bien désallouer un vector<string> reservé ? Reply with quote

Alex wrote:

Quote:
Alex wrote:


Bonjour,
Dans mon programme, j'ai besoin d'avoir un espace contigue de string et
pour cela je fais :

std::vector<string> MesStrings;
MesString.reserve(1000); // <= Si je reserve pas, l'espace
n'est pas contigue et a chaque ajout il me change les adresses
// et dans mon prog il
me faut des adresses qui ne changent pas a chaque ajout


Logiquement ça doit pas être à chaque coup. Quand il ne suffit pas, il doit
te réserver une vingtaine d'éléments d'un coup pour laisser la marge.

Non, l'allocation supplémentaire n'a pas le droit d'être constante, il
faut qu'elle soit multiple de la taille courante. Sinon, on a une
complexitée amortie en O(n) pour l'insertion, au lieu de O(1).


Quote:
Les fuites sont peut-être dues à "un bug" dans STL. C'est que reserve 1000
fait marcher 1000 fois le constructeur de string, qui fait new.

Reserve n'appelle pas de constructeurs. Tu confonds avec resize.


--
Loïc

Back to top
Alex
Guest





PostPosted: Mon Feb 07, 2005 11:47 pm    Post subject: Re: Comment bien désallouer un vector<string> reservé ? Reply with quote

Merci pour ta reponse, mais en fait je viens de m'appercevoir que c'est un
autre vector dans mon prog qui etait mal désalloué... Je m'excuse pour le
"spam", j'aurais du chercher un peu plus avant de poster ici (j'avais cru
avoir cherché assez... mais non !)



"Alex" <no (AT) email (DOT) adresse> a écrit dans le message de news:
cu8tql$idi$1 (AT) apollon (DOT) grec.isp.9tel.net...
Quote:
Alex wrote:

Bonjour,
Dans mon programme, j'ai besoin d'avoir un espace contigue de string et
pour cela je fais :

std::vector<string> MesStrings;
MesString.reserve(1000); // <= Si je reserve pas, l'espace
n'est pas contigue et a chaque ajout il me change les adresses
// et dans mon prog
il
me faut des adresses qui ne changent pas a chaque ajout

Logiquement ça doit pas être à chaque coup. Quand il ne suffit pas, il
doit
te réserver une vingtaine d'éléments d'un coup pour laisser la marge.

En fait, ce que tu appelles l'espace contiguë n'est que l'espace pour
stocker la classe de string, tu vois ce que je vais dire ?
A l'intérieur de celle-ci il y a cependant un ou plusieurs new pour alouer
les tableaux de char où la classe string va stocker ces caractères. Et ça
c'est ton système qui va le faire sur le Heap, quoique si tu développes
ton
propre gestionnaire de mémoire qui va placer toutes tes chaînes dans
l'espace contiguë...

Les fuites sont peut-être dues à "un bug" dans STL. C'est que reserve 1000
fait marcher 1000 fois le constructeur de string, qui fait new. Derrière à
la destruction de ton vector il parcours pour détruire que les éléments
vraiment affectés ensuite.

si tu remplis MesStrings jusqu'à 100, le destructor fait un truc d'en
genre

for(int iElem = 0; iElem < m_nSize; iElem++)
{
delete ...[iElem]; // un tableau où j'sais pas comment il stocke ses trucs
}

où m_nSize égale à la taille réelle du vecteur et non de la mémoire
réservée




Back to top
Loïc Joly
Guest





PostPosted: Mon Feb 07, 2005 11:54 pm    Post subject: Re: Comment bien désallouer un vector<string> reservé ? Reply with quote

Alex wrote:

Quote:
Bonjour,
Dans mon programme, j'ai besoin d'avoir un espace contigue de string et pour
cela je fais :

std::vector<string> MesStrings;
MesString.reserve(1000); // <= Si je reserve pas, l'espace n'est
pas contigue et a chaque ajout il me change les adresses
// et dans mon prog il
me faut des adresses qui ne changent pas a chaque ajout

// J'ajoute kk string
for (int i=0;i<100;i++)
{
string temp = "toto";
MesString.push-back(temp);
}

Ensuite, pour désallouer l'espace je fais :
MesString.clear();

Mon compilateur (vc++) me dit que j'ai des fuites. J'ai noté que si je ne
reserve pas d'espace au debut, je n'ai pas ces memory-leak.

Le bout de code ne me semble pas faux (sauf le push-back au lieu de
push_back, et le fait qu'on réserve 10 fois trop de mémoire). Pour
désallouer, le seul moyen de vraiment faire ça c'est à la destruction de
la variable MesString et il n'y a rien de spécial à faire pour ça (c'est
l'un des intérets de la STL). Donc le code suivant est suffisant et ne
fait pas de fuite mémoire :

int f()
{
std::vector // Juste de l'optimisation, inutile au niveau fonctionnel
// MesString.reserve(1000);
for (int i=0;i<100;i++)
{
string temp = "toto";
MesString.push-back(temp);
}
}


Par contre, ta contrainte de ne pas avoir de réallocation me semble
suspecte, peux-tu développer ?

--
Loïc



Back to top
Alex
Guest





PostPosted: Tue Feb 08, 2005 12:08 am    Post subject: Re: Comment bien désallouer un vector<string> reservé ? Reply with quote


"Loïc Joly" <loic.actarus.joly (AT) wanadoo (DOT) fr> a écrit dans le message de news:
4207feb8$0$17290$8fcfb975 (AT) news (DOT) wanadoo.fr...
Quote:
Alex wrote:

Bonjour,
Dans mon programme, j'ai besoin d'avoir un espace contigue de string et
pour cela je fais :

std::vector<string> MesStrings;
MesString.reserve(1000); // <= Si je reserve pas, l'espace
n'est pas contigue et a chaque ajout il me change les adresses
// et dans mon prog
il me faut des adresses qui ne changent pas a chaque ajout

// J'ajoute kk string
for (int i=0;i<100;i++)
{
string temp = "toto";
MesString.push-back(temp);
}

Ensuite, pour désallouer l'espace je fais :
MesString.clear();

Mon compilateur (vc++) me dit que j'ai des fuites. J'ai noté que si je ne
reserve pas d'espace au debut, je n'ai pas ces memory-leak.

Le bout de code ne me semble pas faux (sauf le push-back au lieu de
push_back, et le fait qu'on réserve 10 fois trop de mémoire). Pour
désallouer, le seul moyen de vraiment faire ça c'est à la destruction de
la variable MesString et il n'y a rien de spécial à faire pour ça (c'est
l'un des intérets de la STL). Donc le code suivant est suffisant et ne
fait pas de fuite mémoire :

int f()
{
std::vector // Juste de l'optimisation, inutile au niveau fonctionnel
// MesString.reserve(1000);
for (int i=0;i<100;i++)
{
string temp = "toto";
MesString.push-back(temp);
}
}


Par contre, ta contrainte de ne pas avoir de réallocation me semble
suspecte, peux-tu développer ?

--
Loïc


Le programme que j'essaie de faire est une DLL. Le programme qui appelle
cette DLL n'enregistre que les pointeurs (en fait c'est un pointeur void*
donc je peux lui passer l'adresse du type que je veux, pour d'autres données
précises comme des char* ou des int je n'ai pas ce probleme - il s'alloue
son espace). Lorsque ma DLL doit donner au prog qui l'apelle une chaine de
caractere, elle lui envoi un pointeur, mais la DLL ne sauve pas dans son
espace la string (comme c'est un void*) et n'enregsitre que le pointeur.
C'est pour cela qu'il me faut un espace contigue, pour qu'a chaque ajout
d'une string, les adresses des strings precedentes (adresses sauvées dans le
prog principal) ne changent pas...

Enfin, j'ai pas trop d'experience en programmation, mais c'est ce que j'ai
compris :)



Back to top
Fabien LE LEZ
Guest





PostPosted: Tue Feb 08, 2005 12:15 am    Post subject: Re: Comment bien désallouer un vector<string> reservé ? Reply with quote

On Mon, 7 Feb 2005 23:16:49 +0100, "Alex" <rdpdo2002 (AT) yahoo (DOT) fr>:

Quote:
MesString.reserve(1000);

Deux remarques en passant :

- évite les "magic values" :

static unsigned const TAILLE_CANONIQUE_TABLEAU= 1000;
MesString.reserve (TAILLE_CANONIQUE_TABLEAU);

- Il me semble que reserve() peut être une no-op (quelqu'un peut
confirmer ?)
De toute façon, si un appel à reserve() change le fonctionnement du
programme (à part bien sûr la vitesse d'exécution), tu as un bug
quelque part.


--
;-)

Back to top
Loïc Joly
Guest





PostPosted: Tue Feb 08, 2005 12:34 am    Post subject: Re: Comment bien désallouer un vector<string> reservé ? Reply with quote

Fabien LE LEZ wrote:

Quote:
On Mon, 7 Feb 2005 23:16:49 +0100, "Alex" <rdpdo2002 (AT) yahoo (DOT) fr>:


MesString.reserve(1000);


Deux remarques en passant :

- évite les "magic values" :

static unsigned const TAILLE_CANONIQUE_TABLEAU= 1000;
MesString.reserve (TAILLE_CANONIQUE_TABLEAU);

- Il me semble que reserve() peut être une no-op (quelqu'un peut
confirmer ?)

Ce n'est pas autorisé par la norme.

Quote:
23.2.4.2
It is guaranteed that no reallocation takes place during insertions that happen after a call to
reserve() until the time when an insertion would make the size of the vector greater than the size
specified in the most recent call to reserve().

--
Loïc

Back to top
Alex
Guest





PostPosted: Tue Feb 08, 2005 1:08 am    Post subject: Re: Comment bien désallouer un vector<string> reservé ? Reply with quote

Quote:
It is guaranteed that no reallocation takes place during insertions that
happen after a call to
reserve() until the time when an insertion would make the size of the
vector greater than the size
specified in the most recent call to reserve().

Une petite question en passant... Si pendant l'execution du prog on se rend
compte que le reserve initial etait trop juste, y-a-til une maniere
d'allouer plus d'espace en gardant la mémoire contigue ? (enfin, disons en
"forcant" l'allocation a etre contigue; quitte a emmettre un message
d'erreur, ou ajuster e programme si cela n'a pas été possible)
Merci




Back to top
Dimitri PAPADOPOULOS-ORFA
Guest





PostPosted: Tue Feb 08, 2005 10:00 am    Post subject: Re: Comment bien désallouer un vector<string> reservé ? Reply with quote

Bonjour,

Quote:
Une petite question en passant... Si pendant l'execution du prog on se rend
compte que le reserve initial etait trop juste, y-a-til une maniere
d'allouer plus d'espace en gardant la mémoire contigue ? (enfin, disons en
"forcant" l'allocation a etre contigue; quitte a emmettre un message
d'erreur, ou ajuster e programme si cela n'a pas été possible)

Autant que je sache, la mémoire utilisée par vector est toujours
contiguë. Si ce n'est pas garanti par la norme actuelle, il me semble
que ça le sera dans la prochaine norme. En attendant, tous les
compilateurs que je connais (re-)allouent toujours un bloc de mémoire
contiguë pour vector.

Back to top
kanze@gabi-soft.fr
Guest





PostPosted: Tue Feb 08, 2005 10:19 am    Post subject: Re: Comment bien désallouer un vector<string> reservé ? Reply with quote

Fabien LE LEZ wrote:
Quote:
On Mon, 7 Feb 2005 23:16:49 +0100, "Alex" <rdpdo2002 (AT) yahoo (DOT) fr>:

MesString.reserve(1000);

- Il me semble que reserve() peut être une no-op (quelqu'un
peut confirmer ?)

Il est même garanti être un no-op si capacity() vaut plus que
son paramètre. Alors, dans une implémentation où le constructeur
initialise le vector avec max_size() capacité systèmatiquement.
(Mais évidemment, je parle des implémentations qu'on ne vera
jamais, parce qu'inutilisable.)

La norme garantit qu'après reserve, capacity() serait au moins
aussi grande que le paramètre de reserve(). Elle garantie aussi
que tant que la taille reste inférieur à cette capacité, les
pointeurs, les références et les itérateurs vers le vecteur
resteront valide. (En fait, ce qui importe, ce n'est pas ce que
fait reserve(), mais ce que ne peut pas faire les autres
fonctions par la suite.)

Quote:
De toute façon, si un appel à reserve() change le
fonctionnement du programme (à part bien sûr la vitesse
d'exécution), tu as un bug quelque part.

Pas du tout. C'est une des b a ba des la durée de vie des
itérateurs. La raison d'être même de réserve, c'est de permettre
des push_back ou des insert par la suite sans invalider les
itérateurs.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Back to top
kanze@gabi-soft.fr
Guest





PostPosted: Tue Feb 08, 2005 10:25 am    Post subject: Re: Comment bien désallouer un vector<string> reservé ? Reply with quote

Alex wrote:
Quote:
It is guaranteed that no reallocation takes place during
insertions that happen after a call to reserve() until the
time when an insertion would make the size of the vector
greater than the size specified in the most recent call to
reserve().

Une petite question en passant... Si pendant l'execution du
prog on se rend compte que le reserve initial etait trop
juste, y-a-til une maniere d'allouer plus d'espace en gardant
la mémoire contigue ? (enfin, disons en "forcant" l'allocation
a etre contigue; quitte a emmettre un message d'erreur, ou
ajuster e programme si cela n'a pas été possible)

Un petit détail : la mémoire d'un std::vector est toujours
contigu. Ça fait partie des exigeances de vector.

Mais je crois en fait que ce dont tu as besoin, c'est que les
adresses des éléments restent valides. Et là, il n'y a rien. Si
tu n'as pas fait un reserve() assez grand, il n'y a rien à
faire.

Ceci dit, j'aimerais savoir un peu plus juste de quoi il s'agit.
Parce qu'il doit y avoir un moyen de contourner le problème.
Donc, par exemple, tu as parlé de renvoyer des void* chez des
clients. Qu'est-ce qu'ils font avec ces void* ? Est-ce que
renvoyer l'adresse du vector (plutôt que l'adresse de son
contenu) ne ferait pas l'affair, par exemple ?

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Back to top
Alex
Guest





PostPosted: Tue Feb 08, 2005 6:00 pm    Post subject: Re: Comment bien désallouer un vector<string> reservé ? Reply with quote

Quote:
Ceci dit, j'aimerais savoir un peu plus juste de quoi il s'agit.
Parce qu'il doit y avoir un moyen de contourner le problème.
Donc, par exemple, tu as parlé de renvoyer des void* chez des
clients. Qu'est-ce qu'ils font avec ces void* ? Est-ce que
renvoyer l'adresse du vector (plutôt que l'adresse de son
contenu) ne ferait pas l'affair, par exemple ?

Alors ca, c'est une très très bonne idée Smile Merci ! (mais pourquoi n'y ai-je
pas pensé plus tot !!)



Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (French) All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.