boost thread를 활용하여 io_context_pool을 만들어서 사용하던 중.. core가 났다
이젠 놀랍지도 않은..
참고한 ThreadPool 예시는 아래에 첨부 링크로 올려두겠다
CMD> ./process
...
/usr/include/boost/smart_ptr/shared_ptr.hpp:728: typename boost::detail::sp_derr<T>::operator*() const [with T = boost::asio::io_context; typename boost::deta_context&]: Assertion `px != 0' failed.
Aborted (core dumped)
그러다 비슷한 에러를 가진 stack overflow 글을 보았는데 내용은 이러했다
일단 원인은, boost 에서 io_context를 얻어오는 함수인 get_executor() 사용시에
임시 객체로 얻어오는 경우에 core가 발생할 수 있다는 것이었다
auto ui_desktop = std::make_shared<desktop>(ui_context.get_executor());
get_executor()는 안에가 어떻게 생겼냐면
/* io_context::get_executor */
executor_type get_executor();
그냥 요렇다
main 함수에서 임시객체 excutor에 get_executor()의 값을 저장해서 사용한다면
main 함수가 끝나면? 이 값은 유효하지 않게 되는 것이다...
그러고 이 값에 다시 접근하면 잘못된 메모리 접근을 해서 문제가 될 수 있다
라는 내용ㅋ
만약 어쩌다 잘 됐다 하더라도 원래 메모리라는게 그 크기만큼 공간이 잡히면
다시 그 메모리 주소에 접근 안하면 문제가 없어 보일 수도 있으니
방심하지말자
답변을 달아준 분은 해결 방법을 아래와 같이 달았다
ui_desktop 개체가 보유한 참조가 유효하도록
get_executor에서 반환된 실행자가 범위를 벗어나지 않는지 확인해라.
예를 들어, get_executor의 결과를 주 변수의 변수에 할당을 해라.
auto executor{ui_context.get_executor()};
auto ui_desktop = std::make_shared<desktop>(executor);
이렇게 ㅋ
참고) object { } 사용
C++ 11에 추가된 초기화 문법인데, 유니폼 초기화라고 부른다
int temp(0);은 안되지만 int temp{0}은 된다 ㅋ
위의 방법은 boost io_context를 좀더 잘 쓰기 위한 방법이니 참고 바라고,
boost 예시에 대한 추가적인 설명을 덧붙이고 끝내겠다
io_context_pool::io_context_pool(std::size_t pool_size)
: next_io_context_(0)
{
if (pool_size == 0)
throw std::runtime_error("io_context_pool size is 0");
// Give all the io_contexts work to do so that their run() functions will not
// exit until they are explicitly stopped.
for (std::size_t i = 0; i < pool_size; ++i)
{
io_context_ptr io_context(new boost::asio::io_context);
io_contexts_.push_back(io_context);
work_.push_back(boost::asio::require(io_context->get_executor(),
boost::asio::execution::outstanding_work.tracked));
}
}
아래 첨부에 링크를 둔 io_context_pool class의 생성자인데,
얘는 work_라는 net::io_context::work를 담아둔 vector에
위에서 언급한 get_executor()를 하나씩 넣어둔다
boost::asio::io_context& io_context_pool::get_io_context()
{
// Use a round-robin scheme to choose the next io_context to use.
boost::asio::io_context& io_context = *io_contexts_[next_io_context_];
++next_io_context_;
if (next_io_context_ == io_contexts_.size())
next_io_context_ = 0;
return io_context;
}
그리고 io_context_pool class에 내부 함수로 get_io_context를 두어
미리 값을 저장한 io_context 값을 가져오도록 구현 되어 있다
실제 코드에서 사용할 때는 아래와 같이 사용하면 된다
void server::start_accept()
{
new_connection_.reset(new connection(
io_context_pool_.get_io_context(), request_handler_));
acceptor_.async_accept(new_connection_->socket(),
boost::bind(&server::handle_accept, this,
boost::asio::placeholders::error));
}
* 참고한 Stack overflow 글 *
https://stackoverflow.com/questions/65534284/boost-asio-segfault-in-release-mode
Boost ASIO segfault in release mode
I have made this small illustrative code that exhibits the same issues the program I'm writing does: namely, it works fine in debug mode, segfaults in release. The problem seems to be that the ui_c...
stackoverflow.com
* boost thread pool example *
doc/html/boost_asio/example/cpp03/http/server2/io_context_pool.cpp - 1.78.0
www.boost.org
'BackEnd > C랑 C++' 카테고리의 다른 글
Boost::program_options 사용기 (0) | 2022.07.26 |
---|---|
전처리기(preprocessor)와 매크로(macro) (0) | 2022.02.07 |
STRUCT와 UNION을 알아보자 (0) | 2021.07.12 |
C++ 스마트 포인터를 알아보자 - (2) shared_ptr (0) | 2021.06.25 |
Error 해결: undefined reference to `vtable for XXX' (0) | 2021.06.24 |