 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Alex Guest
|
Posted: Mon Feb 07, 2005 10:16 pm Post subject: Comment bien désallouer un vector<string> reservé ? |
|
|
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
|
Posted: Mon Feb 07, 2005 10:26 pm Post subject: Re: Comment bien désallouer un vector<string> reservé ? |
|
|
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
|
Posted: Mon Feb 07, 2005 10:30 pm Post subject: Re: Comment bien désallouer un vector<string> reservé ? |
|
|
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
|
Posted: Mon Feb 07, 2005 11:22 pm Post subject: Re: Comment bien désallouer un vector<string> reservé ? |
|
|
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
|
Posted: Mon Feb 07, 2005 11:47 pm Post subject: Re: Comment bien désallouer un vector<string> reservé ? |
|
|
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
|
Posted: Mon Feb 07, 2005 11:47 pm Post subject: Re: Comment bien désallouer un vector<string> reservé ? |
|
|
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
|
Posted: Mon Feb 07, 2005 11:54 pm Post subject: Re: Comment bien désallouer un vector<string> reservé ? |
|
|
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
|
Posted: Tue Feb 08, 2005 12:08 am Post subject: Re: Comment bien désallouer un vector<string> reservé ? |
|
|
"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
|
Posted: Tue Feb 08, 2005 12:15 am Post subject: Re: Comment bien désallouer un vector<string> reservé ? |
|
|
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
|
Posted: Tue Feb 08, 2005 12:34 am Post subject: Re: Comment bien désallouer un vector<string> reservé ? |
|
|
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
|
Posted: Tue Feb 08, 2005 1:08 am Post subject: Re: Comment bien désallouer un vector<string> reservé ? |
|
|
| 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
|
Posted: Tue Feb 08, 2005 10:00 am Post subject: Re: Comment bien désallouer un vector<string> reservé ? |
|
|
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
|
Posted: Tue Feb 08, 2005 10:19 am Post subject: Re: Comment bien désallouer un vector<string> reservé ? |
|
|
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
|
Posted: Tue Feb 08, 2005 10:25 am Post subject: Re: Comment bien désallouer un vector<string> reservé ? |
|
|
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
|
Posted: Tue Feb 08, 2005 6:00 pm Post subject: Re: Comment bien désallouer un vector<string> reservé ? |
|
|
| 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 Merci ! (mais pourquoi n'y ai-je
pas pensé plus tot !!)
|
|
| Back to top |
|
 |
|
|
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
|
|