1

I have a boost::asio::io_context that I want to move around. Since I cannot move it without a pointer, I use an std::unique_ptr. However, I noticed that when running with -fsanitize=address heap-use-after-free.

I checked the pointed to address before and after the move and it is exactly the same. Have I made an error or is the sanitizer just overreacting here?

#include <boost/asio.hpp>
#include <memory>
#include <iostream>

int main()
{
    std::unique_ptr<boost::asio::io_context> io_ptr{
        std::make_unique<boost::asio::io_context>()
    };

    boost::asio::steady_timer timer{*io_ptr, std::chrono::seconds{1}};
    std::cout << "io_ptr address: " << io_ptr.get() << std::endl;
// on my machine: io_ptr address: 0x602000000010

    timer.async_wait([](const boost::system::error_code&) {
        std::cout << "Timer called\n"; // gets called
    });

    std::unique_ptr<boost::asio::io_context> io_ptr2{std::move(io_ptr)};
    std::cout << "io_ptr address: " << io_ptr2.get() << std::endl;
// same: io_ptr address: 0x602000000010
    io_ptr2->run_one();
    std::cout << "Done\n"; // gets printed

    return 0;
}

I tried printing something inside the async_wait call and that gets printed, so the sanitizer happens react to the destruction of the timer it seems.

Compiler: GCC 11.4.0

0

1 Answer 1

6

Keep in mind that destructs happen in reverse order -- which means your second std::unique_ptr, which owns the io_context, is destroyed BEFORE your timer object....

Sign up to request clarification or add additional context in comments.

5 Comments

Of course! I see now. That should be easy to fix. Thanks for pointing out the obvious.
Also, this is only an issue because the io_context must be used in the destructor of the timer.
@SupAl Instead of all the trickiness, just use automatic storage duration and run the service to completion: coliru.stacked-crooked.com/a/16e1d8a7468475f8
@sehe, I tried, but the issue remains - it has nothing to do with being run or not. Only solution is to make sure the io_context is alive when the timer is destroyed.
@SupAl which makes perfect sense considering it's a parameter when constructing the thing too. It's theoretically possible that it's unlinking itself from the io_context when it's not active -- but, it's not documented like that (so common sense dictates to treat it as "it needs the thing for its entire lifetime"), and the sanitizer does suggest that it's not working like that either.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.