2016-03-16 2 views
-1

У меня есть segfault в следующем коде, но я не могу понять, почему ... Я пытаюсь иметь минимальный асинхронный локальный сервер сокетов без использования классов как это делается в примерах, чтобы лучше видеть вызовы. Я был осторожен, чтобы не забыть что-нибудь, но это было 2 часа я ищу, не находя, почему я это Segfault ...Segfault с Asio на async_accept, но не могу понять

Это мой код:

#include <iostream> 
#include <asio.hpp> 

const char * const path = "/var/local/serv.socket"; 
asio::local::stream_protocol::acceptor * acceptor; 
asio::io_service io_service; 

void handle_co(std::error_code ec){ 
    std::cout << ec.message() << std::endl; 
    std::cout << "Connection !"; 
} 

void loop(){ 
    auto socket = new asio::local::stream_protocol::socket(io_service); 
    acceptor->async_accept(*socket, [socket](std::error_code ec){ 
     handle_co(ec); 
     socket->close(); 
     delete socket; 
     loop(); 
    }); 
} 

int main(int argc, char **argv) { 
    std::remove(path); 
    asio::local::stream_protocol::endpoint endpoint(path); 
    asio::local::stream_protocol::acceptor acceptor(io_service); 
    acceptor.open(endpoint.protocol()); 
    acceptor.bind(endpoint); 
    acceptor.listen(); 
    loop(); 

    io_service.run(); 

    return 0; 
} 

... Даже если вы просто должны компилировать и запускать этот код, это то, что valgrind дает мне:

==20787== Invalid read of size 8 
==20787== at 0x418E14: asio::basic_io_object<asio::socket_acceptor_service<asio::local::stream_protocol>, true>::get_service() (basic_io_object.hpp:208) 
==20787== by 0x411909: asio::async_result<asio::handler_type<loop()::{lambda(std::error_code)#1}, void (std::error_code)>::type>::type asio::basic_socket_acceptor<asio::local::stream_protocol, asio::socket_acceptor_service<asio::local::stream_protocol> >::async_accept<asio::local::stream_protocol, asio::stream_socket_service<asio::local::stream_protocol>, loop()::{lambda(std::error_code)#1}>(asio::basic_socket<asio::local::stream_protocol, asio::stream_socket_service<asio::local::stream_protocol> >&, asio::handler_type&&, std::enable_if<std::is_convertible<asio::local::stream_protocol, asio::basic_socket>::value, void>::type*) (basic_socket_acceptor.hpp:1018) 
==20787== by 0x4117BE: loop() (main.cpp:23) 
==20787== by 0x41188C: main (main.cpp:33) 
==20787== Address 0x18 is not stack'd, malloc'd or (recently) free'd 
==20787== 
==20787== 
==20787== Process terminating with default action of signal 11 (SIGSEGV): dumping core 
==20787== Access not within mapped region at address 0x18 
==20787== at 0x418E14: asio::basic_io_object<asio::socket_acceptor_service<asio::local::stream_protocol>, true>::get_service() (basic_io_object.hpp:208) 
==20787== by 0x411909: asio::async_result<asio::handler_type<loop()::{lambda(std::error_code)#1}, void (std::error_code)>::type>::type asio::basic_socket_acceptor<asio::local::stream_protocol, asio::socket_acceptor_service<asio::local::stream_protocol> >::async_accept<asio::local::stream_protocol, asio::stream_socket_service<asio::local::stream_protocol>, loop()::{lambda(std::error_code)#1}>(asio::basic_socket<asio::local::stream_protocol, asio::stream_socket_service<asio::local::stream_protocol> >&, asio::handler_type&&, std::enable_if<std::is_convertible<asio::local::stream_protocol, asio::basic_socket>::value, void>::type*) (basic_socket_acceptor.hpp:1018) 
==20787== by 0x4117BE: loop() (main.cpp:23) 
==20787== by 0x41188C: main (main.cpp:33) 
+0

ли вы запустить программу через отладчик? –

+0

Я предполагаю, что проблема заключается в том, что вы не можете удалить сокет из обработчика 'async_accept'; попробуйте протереть сокет, чтобы подтвердить. –

+0

@BarryTheHatchet yup, но valgrind, как правило, лучше, чем gdb для такого рода вещей ... кроме фрейма стека выглядит странно: segfault происходит в get_service(), а кадр просто сверху - это только «static_cast», который должен не делайте ничего ... –

ответ

0

Проблема в том, что у вас есть столкновения с именами областей. В глобальном масштабе вы объявляете acceptor * acceptor, а затем объявляете acceptor в main() и инициализируете его.

Позже, внутри loop() функция вы используете неинициализированный acceptor* и он падает. Заменить aceptor инициализации, как это и его работы:

acceptor = new asio::local::stream_protocol::acceptor(io_service); 
acceptor->open(endpoint.protocol()); 
acceptor->bind(endpoint); 
acceptor->listen(); 
Смежные вопросы