IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

SL & STL C++ Discussion :

[vector] "vider" un vecteur de un élément ?


Sujet :

SL & STL C++

  1. #1
    Membre du Club
    Homme Profil pro
    Inscrit en
    Février 2009
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2009
    Messages : 37
    Points : 40
    Points
    40
    Par défaut [vector] "vider" un vecteur de un élément ?
    Bonjour à tous,

    J'ai un soucis sur une fonction dont le role est de réaliser une forme de "heartbeat" dans une application client/serveur en mode connecté. En l'occurence le serveur envoie une requete toutes les x secondes aux clients référencés et en cas de non retour de leur part les supprime de la liste de utilisateurs identifiés (et libère effctivement l'espace mémoire alloué).

    Dans le détail mes utilisateurs connectés sont contenus dans un vecteur du type suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::vector<boost::shared_ptr<user> > _users
    sachant que la classe "user" ne contient qu'un seul objet alloué dynamiquement (une socket tcp qui est le lien entre le client et ce user particulier) et des infos générales (nom, IP du client, etc).

    Le code du heartbeat est le suivant (un peu épuré):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    void heartbeat()
    {
    	while (1)
    	{
                    bool errorFound = false;
    		for (vector<boost::shared_ptr<user> >::iterator i = _users.begin(); i != _users.end();  i++)
    		{
     
    // code de la requete et du retour ... send, receive etc
     
    			if (errorFound)
    			{
    				i->reset();
    				_users.erase(i);
    			}
    		}
     
    		// not portable, Windows only due to windows.h
    		Sleep(5000);
    	}
    }
    (à noter que cette fonction est éxécutée dans un thread dédié)

    Sous cette forme ça ne marche pas dans le cas que j'ai testé le premier: un seul utilisateur référencé dans la liste. Le reset du shared_ptr passe (vérifié via un use_count avant/après et un test dans le destructeur de user) par contre vu que le vector n'a qu'un seul élément Windows me crache une erreur comme quoi le vecteur est vide (logique quelque part...).

    J'ai testé avec un mais il n'est pas content non plus vu que i du coup est incrémenté et dépasse _users.end() (si j'ai bien compris).

    Pour l'instant je ne suis pas très chaud à l'idée de traiter ce cas en spécifique avec un _users.clear() si _users.size() egale 1 (j'ai l'impression que l'espace mémoire resterait alloué). J'ai lu ailleurs dans le forum que l'on pourrait utiliser un swap mais j'ai du mal à comprendre avec quoi échanger le vecteur dans ce cas là.

    Quelle solution pensez vous que je devrais implémenter dans mon cas ?

  2. #2
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    i=users.erase(i) devrait fonctionner.
    users.end() n'est pas "dépassé", mais "atteint" si i est positionné sur le dernier élément (qui est aussi le premier quand il n'y en a qu'un). Dans ce cas tu sortirais de la boucle for (et les maniaco-puristes te diront de mettre ++i au lieu de i++).

    EDIT: j'ai parlé trop vite
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    i=users.erase(i);
    --i;

  3. #3
    Membre du Club
    Homme Profil pro
    Inscrit en
    Février 2009
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2009
    Messages : 37
    Points : 40
    Points
    40
    Par défaut
    C'est ce que j'aurai pensé mais il semble que ce ne soit pas le cas: j'ai là une erreur Windows concernant l'itérateur. L'erreur est différente de la première, mais ça crash quand même (et NON Mr Microsoft, je ne vous enverrai jamais de rapport d'erreur )

    EDIT: et j'ai répondu trop vite, je vais essayer avec --i ^^

  4. #4
    Membre chevronné
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    erase invalide les iterators ... Enfin, il y'a une forte probabilité qu'il le fasse.
    "Hardcoded types are to generic code what magic constants are to regular code." --A. Alexandrescu

  5. #5
    Membre expert

    Avatar de IrmatDen
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    1 727
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 727
    Points : 3 266
    Points
    3 266
    Par défaut
    Salut,

    En effet les itérateurs sont invalidés. La bonne façon de faire est donnée dans cette FAQ.

  6. #6
    Membre du Club
    Homme Profil pro
    Inscrit en
    Février 2009
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2009
    Messages : 37
    Points : 40
    Points
    40
    Par défaut
    Effectivement la méthode décrite en itérant selon les cas et non pas directement dans le for( ;; ) marche.

    Merci !

+ Répondre à la discussion
Cette discussion est résolue.

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo