2011-01-05 16 views
0

dies geschieht, wenn eine Struktur der Konstruktion, meinen Code: http://wklej.org/hash/c42680a7f9d/txt/ in dieser Zeile: http://wklej.org/hash/5fefcecc371/txt/ Backtrace: http://wklej.org/id/451070/txt/ jede Hilfe Leider apperciated ist, nicht ich den Code kopieren hier, damit ich es posten an einem anderen Ort;.. (std :: string Copykonstruktor seg Fehler

+0

Warum können Sie Ihren Code hier nicht enthalten? Bitte versuchen Sie, ein kleines Beispiel einzufügen, das Ihr Problem reproduziert. –

Antwort

2

einen Debugger verwenden und eine Stack-Trace erhalten

das Problem an Sicherheit grenzender Wahrscheinlichkeit einen schlechten C-String in den std :: string Konstruktor Vielleicht ist der Zeiger ungültig oder der C-String wird nicht beendet und der Konstruktor liest in den geschützten Speicher aus

Aber ohne weitere Informationen kann ich nicht sagen, was der Fehler ist. Der Debugger sollte sofort darauf hinweisen.

Auch Ihre Socket enthält einen Zeiger, sondern definiert nur einen Konstruktor und Destruktor. Sie benötigen außerdem einen Kopierkonstruktor und einen Zuweisungsoperator. Wenn diese beiden Vorgänge nicht stattfinden sollen, definieren Sie sie als private ohne Implementierung.

Auch ich sehe von Ihrem Backtrace, dass dies eine alte Version von GCC ist. Es ist möglich, dass diese Version nicht über die Korrekturen verfügt, die die Verwendung von std :: string in Multi-Thread-Programmen ermöglichen. Ich weiß nicht, wann es behoben wurde, aber einige ältere Versionen der libstdC++ - Bibliothek blockierten die Referenzzählungen für die Zeichenfolge nicht und konnten abstürzen, wenn verschiedene Threads den Zeichenfolgenspeicher freigaben und gleichzeitig darauf schreiben würden.

+0

backtrace: http://wklej.org/id/451070/txt/ –

+0

@Fallen: Können Sie mit -O0 -g neu erstellen, so dass wir den Wert der Zeichenfolgen in der Backtrace sehen können? Oder gehen Sie zumindest zu Bild 4 und drucken Sie die Werte jedes Funktionsarguments aus. –

+0

@Zan Lynx: http://wklej.org/hash/73b719ed95a/ –

2

ich Ihren Code ein, um sich gelegt haben, um es zu bearbeiten:

#ifdef _WIN32 
    #define _WIN32_WINNT 0x0501 
#endif 

#include <boost/asio.hpp> 
#include <boost/thread.hpp> 
#include <boost/bind.hpp> 
#include <boost/noncopyable.hpp> 
#include <iostream> 
#include <cstdlib> 
#include <cstdio> 
#include <vector> 
#include <sstream> 
#include <string> 

#ifdef assert 
    #undef assert 
#endif 

#define assert(x)\ 
    if (!x) { \ 
     std::clog << "[Error - __FUNCTION__] Asseration to: " << #x << " failed. line: " << __LINE__ << ", file: " << __FILE__ << "." << std::endl;\ 
     std::exit(100);\ 
    } 

template<typename _Tp> 
inline std::string toString(_Tp __p) 
{ 
    std::stringstream ss; 
    ss << __p; 
    std::string ret; 
    ss >> ret; 
    return ret; 
} 

struct Proxy; 

typedef std::vector<Proxy*> ProxyVec; 

struct Proxy 
{ 
    std::string name; 
    uint32_t port; 
}; 

ProxyVec loadProxies(const std::string& fileName) 
{ 
    std::FILE *f = fopen(fileName.c_str(), "r"); 
    if (!f) { 
     std::clog << "[Error - loadProxies] Cannot open: " << fileName << "." << std::endl; 
     delete f; 
     f = NULL; 
     return ProxyVec(); 
    } 

    char buffer[1024]; 
    ProxyVec ret; 
    int32_t __n = 0; 
    while (fgets(buffer, sizeof(buffer), f)) { 
     ++__n; 
     std::string str(buffer); 
     if (str.find("\n") != std::string::npos) 
      str = str.substr(0, str.length()-1); 

     if (str.find("\r") != std::string::npos) 
      str = str.substr(0, str.length()-1); 

     size_t sep = str.rfind(":"); 
     if (sep == std::string::npos) { 
      std::clog << "[Error - loadProxies] Cannot load proxy #" << __n << "." << std::endl; 
      continue; 
     } 

     std::string hostname = str.substr(0, sep); 
     uint32_t port = static_cast<uint32_t>(std::atoi(str.substr(sep+1, str.length()-sep).c_str())); 
     std::clog << "Loading proxy: " << hostname << ":" << port << "." << std::endl; 
     Proxy proxy; 
     proxy.name = hostname; 
     proxy.port = port; 
     ret.push_back(&proxy); 
    } 
    std::clog << "Loaded: " << __n << " proxies." << std::endl; 
    return ret; 
} 

class Socket 
{ 
    public: 
     Socket(boost::asio::io_service& service, const std::string& host, 
      const std::string& port, const std::string& targetHost, const std::string& targetPort); 
     ~Socket(); 

     void write(const std::string& message); 
     std::string receivedData() const; 
     bool connected() const; 
     void receive(); 
     void handle(); 

    private: 
     struct SocketData 
     { 
      SocketData(boost::asio::io_service& service, const std::string& _host, const std::string& _port, 
       const std::string& _targetHost, const std::string& _targetPort): 
       socket(service), 
       write(service), 
       read(service), 
       resolver(service), 
       buffers(), 
       host(_host), 
       port(_port), 
       targetHost(_targetHost), 
       targetPort(_targetPort), 
       connected(false) 
      { 
      } 
      boost::asio::ip::tcp::socket socket; 
      boost::asio::io_service::strand write, read; 
      boost::asio::ip::tcp::resolver resolver; 
      boost::array<char, 1024> buffers; 
      std::string host, port; 
      std::string targetHost, targetPort; 
      bool connected; 
     }; 
      // FIXME: Use shared_ptr instead. 
     SocketData* d; 

    protected: 
     //handle resolve func 
     void handle_resolve(const boost::system::error_code&, 
      boost::asio::ip::tcp::resolver::iterator); 

     //handle connection func 
     void handle_connect(const boost::system::error_code&, 
      boost::asio::ip::tcp::resolver::iterator); 

     //handle write func 
     void handle_write(const boost::system::error_code&, size_t); 

     //handle read func 
     void handle_read(const boost::system::error_code&, size_t); 

    private: 
     void connectionThread(); 
}; 

Socket::Socket(boost::asio::io_service& service, const std::string& host, const std::string& port, 
    const std::string& targetHost, const std::string& targetPort) 
    : d(new SocketData(service, host, port, targetHost, targetPort)) 
{ 
    boost::thread thread(boost::bind(&Socket::connectionThread, this)); 
    // FIXME: This function is blocking. The constructur will never exit. 
    //  Use thread_group.join_all() as last line in main() instead. 
    thread.join(); 
} 

Socket::~Socket() 
{ 
    d->socket.close(); 
    delete d; 
    d = NULL; 
} 

void Socket::connectionThread() 
{ 
    if (!d) 
     return; 

    if (d->connected) 
     return; 

    boost::asio::ip::tcp::resolver::query query(d->host, d->port); 
    d->resolver.async_resolve(query, 
     boost::bind(&Socket::handle_resolve, this, 
      boost::asio::placeholders::error, 
       boost::asio::placeholders::iterator)); 
} 

void Socket::handle_resolve(const boost::system::error_code& e, 
    boost::asio::ip::tcp::resolver::iterator ep_iter) 
{ 
    if (!e) { 
     boost::asio::ip::tcp::endpoint iter = *ep_iter; 
     d->socket.async_connect(iter, 
      boost::bind(&Socket::handle_connect, this, 
       boost::asio::placeholders::error, ++ep_iter)); 
    } else { 
     std::clog << "[Error - Socket::handle_resolve] " << e.message() << "." << std::endl; 
    } 
} 

void Socket::handle_connect(const boost::system::error_code& e, 
    boost::asio::ip::tcp::resolver::iterator ep_iter) 
{ 
    if (!e) { 
     std::cout << "[Notice - Socket::handle_connect] Connected to host." << std::endl; 
     d->connected = true; 
     write("CONNECT " + d->targetHost + ":" + d->targetPort + " HTTP/1.1\r\n\r\n"); 
     receive(); 
    } else if (ep_iter != boost::asio::ip::tcp::resolver::iterator()) { 
     d->socket.close(); 
     boost::asio::ip::tcp::endpoint ep = *ep_iter; 
     d->socket.async_connect(ep, 
      boost::bind(&Socket::handle_connect, this, 
       boost::asio::placeholders::error, ++ep_iter)); 
    } else { 
     std::clog << "[Error - Server::handle_connect] " << e.message() << "." << std::endl; 
    } 
} 

void Socket::handle_write(const boost::system::error_code& e, 
    size_t bytes) 
{ 
    assert(!e || bytes < 0); 
} 

void Socket::handle_read(const boost::system::error_code& e, 
    size_t bytes) 
{ 
    assert(!e || bytes < 0); 
    std::cout << receivedData() << std::endl; 
    receive(); 
} 

void Socket::write(const std::string& message) 
{ 
    boost::asio::async_write(d->socket, boost::asio::buffer(message), 
     d->write.wrap(
      boost::bind(&Socket::handle_write, this, 
       boost::asio::placeholders::error, 
        boost::asio::placeholders::bytes_transferred))); 
} 

std::string Socket::receivedData() const 
{ 
    return std::string(d->buffers.data()); 
} 

void Socket::receive() 
{ 
    d->socket.async_read_some(boost::asio::buffer(d->buffers), 
     d->read.wrap(
      boost::bind(&Socket::handle_read, this, 
       boost::asio::placeholders::error, 
        boost::asio::placeholders::bytes_transferred))); 
} 

void Socket::handle() 
{ 
    assert(!d->targetHost.empty()); 
    assert(!d->targetPort.empty()); 

    std::string str(d->buffers.data()); 
    std::clog << "Received: " << str << "." << std::endl; 
    if (str.substr(0, 4) == "PING") 
     write("PO" + str.substr(2) + "\r\n"); 
    else if (str.find("MODE") != std::string::npos) 
     write("JOIN #OTland\r\n"); 
    else if (str.find("JOIN") != std::string::npos) 
     write("PRIVMSG #OTland :Hello\r\n"); 
} 

bool Socket::connected() const 
{ 
    return d->connected; 
} 

void handler(const std::string& fileName, const std::string& host, const std::string& port, uint32_t threads); 

int main(int argc, char **argv) 
{ 
    if (argc < 5) { 
     std::clog << "[Error - main] Usage: " << argv[0] << " <proxy_file> <host> <port> <threads>" << std::endl; 
     return 1; 
    } 

    std::string file(argv[1]); 
    std::string host(argv[2]); 
    std::string port(argv[3]); 
    uint32_t threads = static_cast<uint32_t>(std::atoi(argv[4])); 
    if (!threads) 
     threads = 1; 

    for (uint32_t __i = 0; __i < threads; ++__i) 
      // FIXME: Use the thread.join() there. 
     handler(file, host, port, threads); 
} 

typedef std::vector<Socket*> SocketVec; 

void handler(const std::string& fileName, const std::string& host, 
    const std::string& port, uint32_t threads) 
{ 
    assert(!fileName.empty()); 
    assert(!host.empty()); 
    assert(!port.empty()); 

    ProxyVec proxies = loadProxies(fileName); 
    assert(proxies.size()); 

    SocketVec sockets; 
    for (ProxyVec::const_iterator it = proxies.begin(); it != proxies.end(); ++it) { 
     boost::asio::io_service io; 
     Socket socket(io, (*it)->name, toString((*it)->port), host, port); 
      // FIXME: socket is a local variable and it's address is invalid outside 
      //  this loop -> memory leak -> seg-fault. 
     sockets.push_back(&socket); 
    } 

    for (SocketVec::const_iterator it = sockets.begin(); it != sockets.end(); ++it) { 
     if (!(*it)->connected()) 
      continue; 

     (*it)->handle(); 
    } 
    // FIXME: I'm not sure if I understand this architecture. A new thread is 
    //  started with this function as handler ? Who waits until this new created 
    //  thread is finished ? Where is the join() ? 
    (void) new boost::thread(boost::bind(handler, fileName, host, port, threads)); 
} 
+0

Sie könnten meinen Beitrag bearbeitet haben, aber trotzdem danke –

+0

Ich habe hinzugefügt __ // FIXME: __ Kommentare mit meinen Bemerkungen im Quellcode. Vielleicht kann der __new__ Code hier gepostet werden, nachdem alle Kommentare gemacht wurden, um vergleichen zu können. –

1

Ich glaube nicht, das einzige Problem ist, aber in diesem Code-Schnipsel in handler, erstellen Sie Ihre Socket Objekte auf dem Stapel. Jedes Socket Objekt, das Sie erstellen, wird am Ende der Schleife for zerstört. Dies bedeutet, dass die Objekte im Vektor ungültige Objekte sind. Dies kann auch den Speicher-Heap so stark beschädigen, dass der angezeigte Fehler auftritt.

SocketVec sockets; 
for (ProxyVec::const_iterator it = proxies.begin(); it != proxies.end(); ++it) { 
    boost::asio::io_service io; 
    Socket socket(io, (*it)->name, toString((*it)->port), host, port); 
    sockets.push_back(&socket); 
} 

Ändern Sie diese an:

SocketVec sockets; 
for (ProxyVec::const_iterator it = proxies.begin(); it != proxies.end(); ++it) { 
    boost::asio::io_service io; 
    Socket* socket = new Socket(io, (*it)->name, toString((*it)->port), host, port); 
    sockets.push_back(socket); 
} 
+0

<3 Danke, dass du darauf hingewiesen hast –

+1

+1 @Fallen du solltest wirklich die [asio examples] durchgehen (http://www.boost.org/doc/libs/1_45_0/doc/html/boost_asio/examples.html) und modelliere deinen Code ähnlich. Zum Beispiel, wenn asynchrone Methoden verwendet werden, ist es sehr empfehlenswert (http://www.boost.org/doc/libs/1_45_0/doc/html/boost_asio/overview/core/threads.html), einen Pool von Threads, die 'io_service :: run' anstelle eines 'io_service' pro Thread aufrufen. –

0

Diese Antwort war ursprünglich ein Kommentar zu Dan's Antwort, aber nach an Ihrem Code suchen fühlte ich mich gezwungen, eine vollständige Antwort zu geben. Sie müssen sich die Boost.Asio examples genauer ansehen und verstehen, wie sie funktionieren. Achte besonders auf die asynchronen Beispiele, es sieht nicht so aus, als hättest du die Konzepte der Lebensdauer von Objekten verstanden und wie die Handler arbeiten. Insbesondere sollten Sie Single-Thread-Programme beherrschen, bevor Sie in mehrere Threads springen. Wenn Sie das erreicht haben, sollten Sie einen Thread-Pool verwenden, der io_service::run statt io_service pro Thread aufruft. Es wird letztendlich die Logik Ihres Programms leichter verständlich machen.

Sie sollten auch schauen in valgrind, gibt es eine ganze Reihe von Fehlern in Ihrem Code wie folgt ein:

==19853== Invalid read of size 4 
==19853== at 0x10000D0E4: handler(std::string const&, std::string const&, std::string const&, unsigned int) (in ./a.out) 
==19853== by 0x10000D5E6: main (in ./a.out) 
==19853== Address 0x7fff5fbff398 is not stack'd, malloc'd or (recently) free'd 
Verwandte Themen