c++gccboost-asiomoveunique-ptr

GCC Address sanitizer bug or invalid move?


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


Solution

  • 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....