Вы столкнулись с неопределенным поведением.
Ваши обработчики фиксируют общие указатели на объекты Service / Work. Но ничто не останавливает main
от выхода, который запустит обработчики выхода и разрушит глобальную библиотечную инфраструктуру. Это не то, что вам нужно.
Проблемы вызваны чрезмерным использованием общих указателей. Общие указатели хороши ТОЛЬКО для совместного владения. В большинстве вашего кода нет общей собственности (main
владеет Сервисом!). Упрощение:
Live On Coliru
#include <boost/asio.hpp>
#include <boost/optional.hpp>
#include <iostream>
#include <memory>
#include <thread>
#include <list>
namespace ba = boost::asio;
class Service {
ba::io_service _service;
boost::optional<ba::io_service::work> _work {_service};
std::list<std::thread> _threads;
public:
~Service() {
_work.reset(); // allow service to complete
for (auto& thread : _threads)
if (thread.joinable())
thread.join();
}
void start() {
_threads.emplace_back([this] {
_service.run();
});
}
ba::io_service& get() { return _service; }
};
class Worker : public std::enable_shared_from_this<Worker> {
ba::io_service& _io;
public:
Worker(Service& service) : _io(service.get()) {}
void work() {
auto self(shared_from_this());
auto workHandler = [self]() {
std::cout << "WorkHandler " << std::endl;
};
_io.post(workHandler);
}
};
int main() {
Service ser;
ser.start();
std::make_shared<Worker>(ser)->work();
}
Печать
WorkHandler
Но самое главное: не вызывает UB и выходит чисто через присоединение потоков.