独立版ASIO与Boost ASIO的HANDLER_TRACKING兼容性问题
独立版ASIO启用Handler Tracking编译失败
问题描述
运行handler_tracking相关的async_tcp_echo_server示例时,Boost版本的ASIO可正常运行并向stderr输出追踪信息,但独立版ASIO编译失败,出现大量asio::detail::handler_tracking::location构造/析构函数的未定义引用,且未使用自定义追踪功能。
复现环境与代码
CMake配置
cmake_minimum_required(VERSION 3.23) project(ASIO_Handler_standalone LANGUAGES CXX) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CPM_DOWNLOAD_VERSION 0.42.0) set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake") if(NOT (EXISTS ${CPM_DOWNLOAD_LOCATION})) message(STATUS "Downloading CPM.cmake") file(DOWNLOAD https://github.com/TheLartians/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake ${CPM_DOWNLOAD_LOCATION}) endif() include(${CPM_DOWNLOAD_LOCATION}) find_library(LIBPTHREAD pthread) # ASIO - standalone with threads set(ASIO_SEPARATE_COMPILATION ON) set(ASIO_DYN_LINK ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON) CPMAddPackage( NAME asiocmake GIT_REPOSITORY "https://github.com/OlivierLDff/asio.cmake" GIT_TAG "main" ) add_executable(foo main.cpp) target_link_libraries(foo asio::asio)
示例代码(main.cpp)
已在包含asio.hpp前定义ASIO_ENABLE_HANDLER_TRACKING:
// // async_tcp_echo_server.cpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #define ASIO_ENABLE_HANDLER_TRACKING #include <cstdlib> #include <iostream> #include <memory> #include <utility> #include <asio.hpp> using asio::ip::tcp; // Define a helper macro to invoke ASIO_HANDLER_LOCATION with the current // file name, line number, and function name. For the function name, you might // also consider using __PRETTY_FUNCTION__, BOOST_CURRENT_FUNCTION, or a hand- // crafted name. For C++20 or later, you may also use std::source_location. #define HANDLER_LOCATION \ ASIO_HANDLER_LOCATION((__FILE__, __LINE__, __func__)) class session : public std::enable_shared_from_this<session> { public: session(tcp::socket socket) : socket_(std::move(socket)) { } void start() { HANDLER_LOCATION; do_read(); } private: void do_read() { HANDLER_LOCATION; auto self(shared_from_this()); socket_.async_read_some(asio::buffer(data_, max_length), [this, self](std::error_code ec, std::size_t length) { HANDLER_LOCATION; if (!ec) { do_write(length); } }); } void do_write(std::size_t length) { HANDLER_LOCATION; auto self(shared_from_this()); asio::async_write(socket_, asio::buffer(data_, length), [this, self](std::error_code ec, std::size_t /*length*/) { HANDLER_LOCATION; if (!ec) { do_read(); } }); } tcp::socket socket_; enum { max_length = 1024 }; char data_[max_length]; }; class server { public: server(asio::io_context& io_context, short port) : acceptor_(io_context, tcp::endpoint(tcp::v4(), port)) { do_accept(); } private: void do_accept() { HANDLER_LOCATION; acceptor_.async_accept( [this](std::error_code ec, tcp::socket socket) { HANDLER_LOCATION; if (!ec) { std::make_shared<session>(std::move(socket))->start(); } do_accept(); }); } tcp::acceptor acceptor_; }; int main(int argc, char* argv[]) { try { if (argc != 2) { std::cerr << "Usage: async_tcp_echo_server <port>\n"; return 1; } asio::io_context io_context; server s(io_context, std::atoi(argv[1])); io_context.run(); } catch (std::exception& e) { std::cerr << "Exception: " << e.what() << "\n"; } return 0; }
编译错误信息
handler_tracking/standalone/main.cpp:39: error: undefined reference to `asio::detail::handler_tracking::location::location(char const*, int, char const*)' ....
(注:存在大量类似的asio::detail::handler_tracking::location构造/析构函数未定义引用错误)
解决方案
问题根源是:独立版ASIO默认未编译handler_tracking相关代码,而项目中启用ASIO_ENABLE_HANDLER_TRACKING后,编译器会尝试引用这些未实现的函数,导致链接错误。
具体修正步骤
在使用CPM添加ASIO库前,增加配置传递启用宏:
// ... 其他配置不变 ... # ASIO - standalone with threads set(ASIO_SEPARATE_COMPILATION ON) set(ASIO_DYN_LINK ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON) # 新增:传递handler_tracking启用宏给ASIO库编译流程 set(ASIO_OPTIONS ASIO_ENABLE_HANDLER_TRACKING) CPMAddPackage( NAME asiocmake GIT_REPOSITORY "https://github.com/OlivierLDff/asio.cmake" GIT_TAG "main" ) // ... 其他配置不变 ...
原理说明
Boost版本的ASIO默认包含了handler_tracking的编译支持,而独立版ASIO通过asio.cmake引入时,默认不会启用该宏。通过ASIO_OPTIONS传递宏参数,让ASIO库在编译时生成handler_tracking相关代码,即可解决链接时的未定义引用问题。
内容的提问来源于stack exchange,提问作者ArchNemSyS
相关产品推荐
相关产品推荐

