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

Boost C++ Discussion :

[Smart Ptr] Problème de pointeur avec ASIO


Sujet :

Boost C++

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2011
    Messages
    66
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Avril 2011
    Messages : 66
    Points : 37
    Points
    37
    Par défaut [Smart Ptr] Problème de pointeur avec ASIO
    Bonjour à tous,

    pour expliquer grossièrement le topo, mon application P2P se connecte au démarrage aux autres applications en cours de fonctionnement, et stocke chaque connexion réussie dans un tableau de pointeurs intelligents (smart_ptr).

    Normalement, lorsqu'il y a un problème de connexion (erreur de lecture), ou une déconnexion volontaire, je ferme mon socket (via un m_socket.close()). Là, le compteur de référence de ma connexion doit normalement tomber à 0, et le shared_ptr doit libérer la mémoire automatiquement.

    Le problème est que lorsque je fais un close(), mon compteur de référence est à 2, et tombe à 1 après la fermeture. La mémoire n'est donc pas libérée car il me reste une référence sur mon pointeur de connexion que je n'arrive pas à trouver. A savoir que j'utilise une surcouche SSL pour mes connexions (Peut-être que ça vient de là). Voici mon code en version simplifiée:

    Ma Classe principale qui possède toutes les connexions:
    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
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
     
    class node:
    {
    public:
            node(boost::asio::io_service& io_service,std::string ip,int port);
     
    private:
            boost::array <connec::pointer,NB_CONNEC_MAX> allSuperNodes;
            boost::asio::io_service& m_io_serv;
            tcp::endpoint m_listening_endpoint;
            boost::asio::ssl::context m_context;
     
            void connectRemoteNodes()
            {
        // On récupère la liste des Nodes pour s'y connecter
        boost::asio::ip::tcp::resolver resolver(m_io_serv);
        boost::asio::ip::tcp::resolver::query query(".................", "7171");
        boost::asio::ip::tcp::resolver::iterator iter = resolver.resolve(query);
        boost::asio::ip::tcp::resolver::iterator end; //Marqueur de fin
     
        while (iter != end) // Pour chaque Node
        {
            boost::asio::ip::tcp::endpoint endpoint = *iter++;
            if(endpoint.address().to_string().compare(m_listening_endpoint.address().to_string())!=0)
            {
                try{
                    connect(endpoint);
                }catch(const std::exception & e){
                    std::cout<<"ERREUR: "<< e.what() <<std::endl;
                }
            }
        }
    void connect(tcp::endpoint& endpoint)
    {
    	connec::pointer new_node= connec::createConnec(m_io_serv,m_context);
        new_node->socket().async_connect(	endpoint, boost::bind(&nvsnode::handle_connect, this, new_node, endpoint.address().to_string(), boost::asio::placeholders::error));
    }
     
    void nvsnode::handle_connect(connec::pointer new_node,const std::string addr,const boost::system::error_code& error)
    {
        int i=0;
        if(!error)
        {
            while(allSuperNodes[i]!=NULL && i<NB_CONNEC_MAX)
                i++;
            if(i<NB_CONNEC_MAX)
            {
                // On sauvegarde le pointeur vers la connexion
                allSuperNodes[i]=new_node;
                // On lance le socket
                allSuperNodes[i]->start(AS_CLIENT);
            }
            else
            {
                std::cout<<"Nombre de connexion maximum atteint ("<<NB_CONNEC_MAX<<")"<<std::endl;
            }
        }
        else
        {
            std::cout   <<"Connexion échouée à "<<addr<<": "<<error.message() << std::endl;
        }
    }
    }
    };
    Ma classe de connexion:
    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
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
     
    typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> ssl_socket;
     
    class connec: public boost::enable_shared_from_this<connec>
    {
        public:
    		typedef boost::shared_ptr<connec> pointer;
     
    		static pointer createConnec(boost::asio::io_service& io_service,boost::asio::ssl::context& context)
    {
    	return connec::pointer(new connec(io_service,context));
    }
     
            void start(int client_server)
    {
    	if(client_server==AS_CLIENT)
    	{		m_socket.async_handshake(boost::asio::ssl::stream_base::client,					boost::bind(&connec::handle_handshake,shared_from_this(),boost::asio::placeholders::error));
    	}
    	if(client_server==AS_SERVER)
    	{
    		m_socket.async_handshake(boost::asio::ssl::stream_base::server,					boost::bind(&connec::handle_handshake,shared_from_this(),boost::asio::placeholders::error));		
    	}
    }
            ssl_socket::lowest_layer_type& socket()
    {
    return m_socket.lowest_layer();
    }
     
    private:
            ssl_socket m_socket;
            boost::array <char,1> read_buf;
     
            connec(boost::asio::io_service& io_service,boost::asio::ssl::context& context)
    :m_socket(io_service,context)
    {
    	m_socket.set_verify_mode(boost::asio::ssl::verify_peer);
    }
     
            void handle_handshake(const boost::system::error_code& error)
    {
    if(!error)
    	{
    		read();
    	}
    	else
    	{
    		std::cout<< "Error: "<< error.message()<<std::endl;
    	}
    }
            void read()
    {
    boost::asio::async_read(m_socket,
    			boost::asio::buffer(read_buf),
    			boost::bind(&connec::handle_read,shared_from_this(),
    					boost::asio::placeholders::error,
    					boost::asio::placeholders::bytes_transferred));
    }
            void handle_read(const boost::system::error_code& error, size_t bytes_transfered)
    {
    	if(!error)
    	{
    		std::cout<<"Received: "<<read_buf.data()<<std::endl;
    		read();
    	}
    	else
    	{
    		m_socket.shutdown();
    		m_socket.lowest_layer().close();
    	}
    }
    };
    Voilà le principe, je ne sais pas trop d'où provient cette référence sur mon pointeur, et connaissant peu shared_ptr (je m'y mets justement), je ne sais pas si il existe un moyen de connaître le type de reference qui reste après mon close().

    Si une bonne âme passe par là et à la patience de se pencher sur le problème... Merci d'avance !

    PS: Désolé pour le formatage approximatif du code, la mise en page dans la balise est compliquée, j'ai fait au mieux.

  2. #2
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par Raz-X Voir le message
    Voilà le principe, je ne sais pas trop d'où provient cette référence sur mon pointeur, et connaissant peu shared_ptr (je m'y mets justement), je ne sais pas si il existe un moyen de connaître le type de reference qui reste après mon close().
    Je n'ai pas lu ton code (n'ayant encore jamais utilisé ASIO), mais voici quelques conseils généraux.

    Est-ce que quand tu quittes ton programme, le comptage de référence passe à 0, et l'objet est bien détruit ?
    - Si oui, mets un point d'arrêt dans le destructeur de ton objet, et quand il se déclenches, regarde dans la pile d'appels ce qui a finalement fait passer à 0 ton compteur, tu tiens là le coupable.
    - Si non, je te conseille une revue de code, en faisant en particulier attention aux références circulaires (à casser à l'aide de weak_ptr).

    Tu peux aussi mettre un point d'arrêt à chaque incrément du compteur de référence, pour voir qui en tient une, mais à moins de bien connaître ton outil de debug et de mettre le point d'arrêt sur l'incrément du compteur en particulier qui pose problème, tu risques d'avoir pas mal de faux positifs.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  3. #3
    Nouveau membre du Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2011
    Messages
    66
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Avril 2011
    Messages : 66
    Points : 37
    Points
    37
    Par défaut
    Bonjour JolyLoic,

    merci beaucoup pour cette réponse, je n'ai en effet pas pensé à regarder si l'objet était bien détruit lors de la fermeture de mon programme. Je vais donc tester cette technique de Debug, et vous tiendrai au courant de l'avancée.

    Bonne journée.

Discussions similaires

  1. Réponses: 4
    Dernier message: 28/05/2008, 00h55
  2. Problème de pointeurs avec un tableau
    Par Tom_Tom_RoF dans le forum Fortran
    Réponses: 8
    Dernier message: 05/10/2007, 17h34
  3. problème de pointeur avec les listes chainees
    Par innosang dans le forum C
    Réponses: 9
    Dernier message: 30/12/2005, 15h46
  4. Problèmes de pointeurs avec les arbres
    Par thierry57 dans le forum C
    Réponses: 17
    Dernier message: 22/12/2005, 23h35
  5. Problème de pointeur avec un TQuery
    Par Oluha dans le forum Bases de données
    Réponses: 3
    Dernier message: 25/01/2005, 13h57

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