2012-01-25 10 views
10

Aby dowiedzieć się C++ 11 (i doładowania) Piszę prosty serwer http używając boost asio i C++ 11 (dla wątków i lambdas).Uruchamianie std :: wątku z łączeniem statycznym powoduje uszkodzenie segmentacji

Chcę przetestować nową C++ 11 lambdy i std :: wątek więc próbowałem uruchomić io_service.run() takiego w std :: nici z lambda:

#include <iostream> 
#include <thread> 
#include <boost/asio.hpp> 
#include <boost/thread.hpp> 
using std::cout; 
using std::endl; 
using boost::asio::ip::tcp; 

class HttpServer 
{ 
public: 
    HttpServer(std::size_t thread_pool_size) 
    : io_service_(), 
    endpoint_(boost::asio::ip::tcp::v4(), 8000), 
    acceptor_(io_service_, endpoint_) 
    { } 

    void Start() { 
     acceptor_.listen(); 
     cout << "Adr before " << &io_service_ << endl; 
     std::thread io_thread([this](){ 
      cout << "Adr inside " << &io_service_ << endl; 
      io_service_.run(); 
     }); 
     io_thread.join(); 
    } 

private: 
    boost::asio::io_service io_service_; 
    tcp::endpoint endpoint_; 
    tcp::acceptor acceptor_; 
}; 

int main() { 
    HttpServer server(2); 
    server.Start(); 
} 

ten kończy się z segmentacji wina. Dodatkowo czasami działa cout wewnątrz lambda, czasami nie (chociaż endl powinien się spłukiwać). W każdym razie drukuje prawidłowy adres io_service_. Jednak po wymianie std::thread na boost::thread (żadnych innych zmian!) Wszystko działa poprawnie.

Byłbym wdzięczny, jeśli ktoś ma pomysł, gdzie powstał problem (może być asio, std :: thread lub std :: lambda).

Dodatkowe informacje:

Według innej post uzyskującego dostęp do io_service_ członka w lambda jest w porządku, gdy przechwytywanie this, jak to zrobić.

Używam gcc 4.6.1 na Ubuntu i zwiększam 1,46. G ++ parametry:

g++ -std=c++0x -static -I/home/andre/DEV/boost_1_48_0/include/ -L/home/andre/DEV/boost_1_48_0/lib/ -o webserver main.cpp -lboost_system -lboost_thread -lpthread 

Aktualizacja:

Usuwanie -static rozwiązaniu problemu. Odkryłem, że problem nie ma nic wspólnego z boost lub lambdami i może być odtwarzany przy każdym budowaniu statycznym i przy użyciu std::thread. Z jakiegokolwiek powodu ta kombinacja nie działa. Myślę, że ten post opisuje prawie to samo, jednak tak naprawdę nie rozumiem szczegółów, a komunikat o błędzie jest inny.

Więc zastanawiam się, dlaczego std::thread i łączenie statyczne nie działają razem. Czy istnieje powód, dla którego link statyczny nie jest tu dozwolony? Zaktualizowałem tytuł pytania i usunąłem tag boost.

+0

Wiem, że powyższy kod nic nie robi w tej chwili. Zostawiłem tylko to, co jest istotne dla opisanego problemu ... –

+0

Czy próbowałeś go uruchomić w debugerze, aby zobaczyć, gdzie jest błąd segmentacji? –

+1

@JoachimPileborg przepraszam, ominąłem to. Segfault był czasami w pierwszej linii lambda (cout << ...), a drugi razy w drugiej linii (io_service_.run();). W końcu dowiedziałem się, że nie ma to nic wspólnego z boostem lub lambdasem, ale z łączeniem statycznym i std :: thread. Usunięcie -static rozwiązało problem. Znalazłem podobny post opisujący takie [problemy] (http://stackoverflow.com/questions/7090623/c0x-thread-static-linking-problem). –

Odpowiedz

6

Zdjęcie -static rozwiązało problem. Dowiedziałem się, że nie ma to nic wspólnego z boost lub lambdas, ale z łączami statycznymi i std::thread, które nie działają ze sobą z jakiegokolwiek nieznanego powodu (patrz także ten post, który może być powiązany).

Myślę, że pytanie, dlaczego nie współpracują ze sobą, jest - choć interesujące - poza zakresem na razie i cieszę się z odpowiedzi, więc można to oznaczyć jako odpowiedź.

6

Połączyć aplikację z -Wl,--whole-archive -lpthread -Wl,--no-whole-archive Więcej tutaj https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52590 To działa dla mnie.

+2

jest to płaczliwy wstyd, że nawet w gcc 6.2 wynik samego połączenia z '-static -pthread' spowoduje złamanie plików wykonywalnych (np. błędy runtime) i brak błędów łącznika, a nawet ostrzeżeń. Musiałem poświęcić kilka godzin na debugowanie, aby dowiedzieć się, że problem jest znany od czasu wydania gcc 4.7 i został rozwiązany jako "RESOLVED INVALID". Twoja odpowiedź w końcu wskazała mi, co robiłem źle. – Julian

+1

Jesteś ratownikiem. Dzięki! –

Powiązane problemy