shared_from_this verursacht bad_weak_ptr
Ich versuche zu halten, wird eine Liste der angeschlossenen clients in asio. Ich habe an die chat-server-Beispiel aus der Doku (http://www.boost.org/doc/libs/1_57_0/doc/html/boost_asio/example/cpp03/chat/chat_server.cpp) und hier ist der wichtige Teil von dem, was ich endete mit:
#include <iostream>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/asio.hpp>
#include <set>
using boost::asio::ip::tcp;
class tcp_connection;
std::set<boost::shared_ptr<tcp_connection>> clients;
void add_client(boost::shared_ptr<tcp_connection> client)
{
clients.insert(client);
}
class tcp_connection : public boost::enable_shared_from_this<tcp_connection>
{
public:
tcp_connection(boost::asio::io_service& io_service) : socket_(io_service)
{
}
tcp::socket socket_;
void start()
{
add_client(shared_from_this());
}
tcp::socket& socket()
{
return socket_;
}
};
class tcp_server
{
public:
tcp_server(boost::asio::io_service& io_service)
: io_service_(io_service),
acceptor_(io_service, tcp::endpoint(tcp::v4(), 6767))
{
tcp_connection* new_connection = new tcp_connection(io_service_);
acceptor_.async_accept(new_connection->socket(),
boost::bind(&tcp_server::start_accept, this, new_connection,
boost::asio::placeholders::error));
}
private:
void start_accept(tcp_connection* new_connection,
const boost::system::error_code& error)
{
if (!error)
{
new_connection->start();
new_connection = new tcp_connection(io_service_);
acceptor_.async_accept(new_connection->socket(),
boost::bind(&tcp_server::start_accept, this, new_connection,
boost::asio::placeholders::error));
}
}
boost::asio::io_service& io_service_;
tcp::acceptor acceptor_;
};
int main()
{
try
{
boost::asio::io_service io_service;
tcp_server server(io_service);
io_service.run();
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
Beim Aufruf shared_from_this, mein server stürzt ab mit der Meldung "Exception: tr1::bad_weak_ptr." Ich habe getan, einige suchen, und es scheint shared_from_this()
ziemlich allem, aber ich kann nicht scheinen, um herauszufinden, genau das, was ich ändern muss.
Kommentar zu dem Problem - Öffnen
Warum speichern Sie das Ergebnis von
new
in einem raw-pointer verwenden Sie nur shared_from_this()
später? Es scheint Ihr design vereinfacht werden könnte um dieses problem zu beseitigen insgesamt. Die boost-docs für
enable_shared_from_this
sagen Es muss vorhanden sein, mindestens eine shared_ptr-Instanz p besitzt t
, die Sie scheinen nicht zu haben. @JonathanPotter ich gelesen, aber ich verstehe es nicht.
@chrisvj Meine interpretation ist, müssen Sie bereits eine
shared_ptr
, die das Objekt beinhaltet, bevor Sie mehr machen können mit shared_from_this
. Es nie benutzt mich, aber so ist es nur eine Vermutung. @JonathanPotter Hmm, nicht wissen, nicht sehen, nichts mit shared_ptr in dem Beispiel, das ich nicht habe.
InformationsquelleAutor der Frage chrisvj | 2014-12-30
Du musst angemeldet sein, um einen Kommentar abzugeben.
John Zwinck die wesentliche Analyse ist vor Ort auf:
Jedoch, sein Rat scheint völlig abwegig und gefährlich Asio-code.
Sollten Sie dies lösen, indem Sie - in der Tat - nicht mit rohen Zeigern auf
tcp_connection
an Erster Stelle, aber immer mitshared_ptr
statt.boost::bind
hat das Super feature, dass es bindet anshared_ptr<>
nur gut, also es hält automatisch den Spitzen zum Objekt lebt so lange, wie einige der asynchrone Betrieb Betrieb auf.Diese - in deinem Beispiel-code - Mittel, die Sie nicht brauchen, die
clients
Vektor, gehen den umgekehrten Weg von John ' s Antwort:Habe ich ein Beispiel, das macht
tcp_connection
tun einige triviale Arbeit (es-Schleifen schreiben 'Hallo Welt' auf der client jede Sekunde, bis der client löscht die Verbindung. Wenn es funktioniert, können Sie den Destruktor dertcp_connection
operation ausgeführt wird:Live Auf Coliru
Typische Ausgabe:
InformationsquelleAutor der Antwort sehe
Der Fehler ist, dass Sie
shared_from_this()
auf ein Objekt, das hat keineshared_ptr
verweisen. Dies verstößt gegen die Voraussetzung dershared_from_this()
nämlich, dass mindestens einshared_ptr
muss bereits erstellt wurden (und noch existieren), das aufthis
.Die Ursache Ihrer Beschwerden zu sein scheint, die Tatsache, dass Sie speichern das Ergebnis der
new
in einem raw-pointer zunächst. Speichern Sie das Ergebnisnew
in einen smart-pointer (immer, im Grunde). Vielleicht können Sie speichern Sie die smart-pointer in Ihrerclients
Liste sofort, dann.Ein weiterer Ansatz, die ich bereits in den Kommentaren ist das halt mit
shared_from_this()
ganz. Sie brauchen es nicht. Für dieses bisschen code, den Sie erwähnt:Können Sie ersetzen Sie es durch:
Ist, erstellen Sie eine "dumme" smart-pointer, die nie freigeben ( https://stackoverflow.com/a/5233034/4323 ), aber die wird Sie geben, was Sie brauchen, um es zu löschen von der Liste der clients. Es gibt andere Möglichkeiten, es zu tun, wie mit der Suche im
std::set
mit einem Vergleich-Funktion, die eineshared_ptr
- und ein raw-pointer und weiß zu vergleichen, die Adressen, auf die Sie zeigen. Es spielt keine große Rolle, welchen Weg Sie wählen, aber Sie entkommen dershared_from_this()
situation vollständig.InformationsquelleAutor der Antwort John Zwinck