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:
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 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; } } } };
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().
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(); } } };
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.
Partager