【问题标题】:Compilation error when including boost/thread.cpp包含 boost/thread.cpp 时的编译错误
【发布时间】:2012-07-28 15:09:33
【问题描述】:

我有以下代码使用 Boost ASIO 来设置 TCP 客户端。这是我的代码改编自 Boost 文档的chat example

class AsioCommunicationService {
AsioCommunicationService::AsioCommunicationService(
        boost::asio::io_service& io_service,
        tcp::resolver::iterator endpoint_iterator)
    : io_service_(io_service),
      socket_(io_service)
{
    tcp::endpoint endpoint = *endpoint_iterator;
    socket_.async_connect(endpoint,
    boost::bind(&AsioCommunicationService::handle_connect, this,
    boost::asio::placeholders::error, ++endpoint_iterator));
}

void AsioCommunicationService::handle_connect(const boost::system::error_code& error,
        tcp::resolver::iterator endpoint_iterator)
{
    if (!error)
    {
      boost::asio::async_read(socket_,
          boost::asio::buffer(read_msg_.data(), LampMessage::header_length),
          boost::bind(&AsioCommunicationService::handle_read_header, this,
          boost::asio::placeholders::error));
    }
}
}


class Connection
{
    //init io_service, query, resolve, iterator here
    boost::asio::io_service io_service;
    boost::asio::ip::tcp::resolver resolver(io_service);
    boost::asio::ip::tcp::resolver::query query(host, service);
    boost::asio::ip::tcp::resolver::iterator endpoint_iterator =
  resolver.resolve(query);


    m_session = std::shared_ptr<AsioCommunicationService>(
            new AsioCommunicationService(io_service, iterator));

    //start new thread for io_service.run --> GOT AN ERROR when include boost/thread.hpp
    boost::thread t(boost::bind(&boost::asio::io_service::run, &io_service));

    //this synchronous command would work, but it's blocking the program. I don't want that.
    //io_service.run();
}

当然,我需要包含 boost/thread 才能在 Connection 类中对变量 t 进行声明。但是当我这样做时,我得到了这个错误

#include <boost/thread.hpp>
//ERROR: In function ‘boost::thread&& boost::move(boost::thread&&)’:
///usr/include/boost/thread/detail/thread.hpp:349:16: error: invalid initialization of reference of type ‘boost::thread&&’ from expression of type ‘boost::thread’
//In file included from /usr/include/boost/thread/detail/thread_heap_alloc.hpp:17:0,
//             from /usr/include/boost/thread/detail/thread.hpp:13,
//             from /usr/include/boost/thread/thread.hpp:22,
//             from /usr/include/boost/thread.hpp:13,
//             from /home/son/dev/logistics/src/frameworks/networkService/NetworkConnection.cpp:13:
///usr/include/boost/thread/pthread/thread_heap_alloc.hpp: In function ‘T* boost::detail::heap_new(A1&&) [with T = boost::detail::thread_data<void (*)()>, A1 = void (*&)()]’:
///usr/include/boost/thread/detail/thread.hpp:130:95:   instantiated from here
///usr/include/boost/thread/pthread/thread_heap_alloc.hpp:24:47: error: cannot bind ‘void (*)()’ lvalue to ‘void (*&&)()’
///usr/include/boost/thread/detail/thread.hpp:43:13: error:   initializing argument 1 of ‘boost::detail::thread_data<F>::thread_data(F&&) [with F = void (*)()]’

如果我删除 boost/thread.hpp 的包含,它会编译并工作,并通过简单调用 io_service.run(); 将声明替换为 t;我想知道这个编译错误是否与 boost 版本有关。如果有任何帮助,我正在使用 Boost ASIO 1.42、Ubuntu 11.04 和 Eclipse。提前谢谢你。

【问题讨论】:

  • 您能否尝试将其简化为一个独立的小示例,以便人们进行试验?
  • Boost 1.42 已经过时了(从 2010 年 afaics 开始)。至少有一些错误消息引用了右值引用,它是 C++11 标准的一部分,在当时一定是非常先进的。可能仍然存在许多粗糙的边缘。我会尝试使用最新版本的 boost,看看是否能解决您的问题。
  • 感谢@MvG,基本上当我将包含 放在我的代码中时,我得到了这些错误。我认为其余的都不重要。

标签: c++ multithreading boost boost-asio boost-thread


【解决方案1】:

我编写了一个包含单个包含指令的文件:

#include <boost/thread.hpp>
  • g++-4.5.4 -std=c++0x -I /usr/include/boost-1_42 -c 给出了你提到的错误。
  • g++-4.6.3 -std=c++0x -I /usr/include/boost-1_42 -c同理
  • g++-4.7.1 -std=c++0x -I /usr/include/boost-1_42 -c 错误更多
  • g++-4.7.1 -std=c++0x -I /usr/include/boost-1_49 -c 没有一个错误
  • g++-4.6.3g++-4.5.4 使用 boost 1.49 也可以正常工作

因此,我真的建议您为此使用更新版本的 boost。您不必在系统范围内安装它,而是可以为单个用户安装它。所以你不依赖于 ubuntu 包。

要手动安装 boost,我建议你按照Getting Started on Unix Variants 指南:

  1. boost_1_50_0.tar.bz2 解压到某个临时源目录,然后将cd 解压到该目录中
  2. Build and install 使用 ./bootstrap.sh --prefix=${HOME}/boost_1_50 &amp;&amp; ./b2 install
  3. Compile 您的应用程序使用 -I ${HOME}/boost_1_50 获取正确的标头
  4. linking 您的应用程序时,将${HOME}/boost_1_50/lib/libboost_thread.a 包含为参数

使用静态libboost_thread.a 而不是动态libbtoost_thread.so 将确保您不必担心查找库来启动应用程序。您需要的来自 boost 的所有内容都将包含在您的主二进制文件中。

【讨论】:

  • 谢谢。你如何建议我在我的 ubuntu natty 上安装 boost 1.49 或 1.50?我似乎无法为它找到一个ppa。那我应该下载并重新编译boost吗?
  • @SonDo,我的回答中包含了安装 boost 的快速指南。
  • 感谢@MvG。我成功构建并安装了 boost(但我忽略了一些,并跳过了。我不知道为什么)。然后用这个“g++-4.5 -std=c++0x -I ${HOME}/boost_1_50 test.cpp -c”编译我的示例代码仍然给我同样的错误。嗯,我现在真的很生气,在这件事上花了2天没有任何进展。如果您能帮我解决这个问题,我将不胜感激。
  • 你能告诉我如何在同一台机器上安装不同版本的g++吗?谢谢。
  • @SonDo,使用-E 编译以仅运行预处理阶段。结果应该告诉您实际包含了哪些头文件。这应该告诉您旧的标头是否被意外使用。至于安装 g++:按照the manual 安装,在您的${HOME} 下的某处也使用--prefix
【解决方案2】:

按照 C++11 标准的@MvG 的推理路线,我做了一些研究。看来是a problem of coordination在Ubuntu Natty提供的gcc和boost之间,分别使用了-std=c++0x和libboost1.42。

没有解决方案,但我使用了这个解决方法:在 /usr/include/boost/config/compiler/gcc.hpp 中注释掉# define BOOST_HAS_RVALUE_REFS,如下所示。

#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2)) && defined(__GXX_EXPERIMENTAL_CXX0X__)
// C++0x features are only enabled when -std=c++0x or -std=gnu++0x are
// passed on the command line, which in turn defines
// __GXX_EXPERIMENTAL_CXX0X__.
# define BOOST_HAS_DECLTYPE
//# define BOOST_HAS_RVALUE_REFS
# define BOOST_HAS_STATIC_ASSERT
# define BOOST_HAS_VARIADIC_TMPL
#else

我的代码现在可以像魔术一样编译了:) 谢谢@MvC。

【讨论】:

    【解决方案3】:

    经过大量探索,按照@MvG的建议,我通过以下操作成功编译并链接了我的简单程序:

    • 手动构建和安装 boost 1.50(使用 MvG 建议)
    • 使用以下 2 个 make 文件(1 个用于静态链接,1 个用于动态链接)编译和链接源代码。

    动态:

    default: test
    
    test.o: test.cpp
        g++-4.5 -std=c++0x -I /home/son/boost_1_50/include/ -c test.cpp 
    
    test: test.o        
        g++-4.5 -std=c++0x -L /home/son/boost_1_50/lib/ test.o -lboost_thread -lboost_system -lboost_chrono -pthread -o test
    
    run: test
        LD_LIBRARY_PATH=/home/son/boost_1_50/lib/ ./test
    

    静态:

    default: test
    
    test.o: test.cpp
        g++-4.5 -std=c++0x -I /home/son/boost_1_50/include/ -c test.cpp 
    
    test: test.o
        g++-4.5 -std=c++0x -L /home/son/boost_1_50/lib/ test.o -static -lboost_thread -lboost_system -lboost_chrono -pthread -o test
    
    run: test
        ./test
    

    test.cpp文件如下。

    #include <boost/thread.hpp>
    #include <stdio.h>
    
    int main()
    {
        printf("boost thread tested by son\n");
        boost::thread t;
        return 0;
    }
    

    就是这样。我在用 CMake 编译它时遇到了困难,但这是另一个问题。

    【讨论】:

    • -static 链接不仅在 boost 中静态链接,还包括大部分 libc 和 libstdc++。不确定这是否真的是个好主意。
    • 是的,如您所解释的那样,直接静态链接到 .a 是另一种替代方式。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2023-01-11
    • 2019-05-23
    • 2010-09-30
    • 1970-01-01
    • 2013-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多