【问题标题】:Segmentation fault in std::thread::id's std::operator==std::thread::id 的 std::operator== 中的分段错误
【发布时间】:2014-06-23 08:37:33
【问题描述】:

我遇到了一个不知道如何解决的问题。我相信这是 GCC 和/或 libstdc++ 中的问题。

我正在运行带有 GCC 4.8.2-19ubuntu1、libstdc++3.4.19(我相信?How do you find what version of libstdc++ library is installed on your linux machine?)和 boost 1.55 的 Ubuntu 14.04 LTS。

代码如下:

// http://www.boost.org/doc/libs/1_54_0/libs/log/doc/html/log/tutorial.html
// with a slight modification to ensure we're testing with threads too
// g++ -g -O0 --std=c++11 staticlinktest.cpp -lboost_log_setup -lboost_log -lboost_system -lboost_filesystem -lboost_thread -lpthread

#define BOOST_ALL_DYN_LINK 1

#include <boost/log/trivial.hpp>

#include <thread>
#include <atomic>
#include <vector>

int main(int, char*[])
{
    BOOST_LOG_TRIVIAL(trace) << "A trace severity message";
    BOOST_LOG_TRIVIAL(debug) << "A debug severity message";
    BOOST_LOG_TRIVIAL(info) << "An informational severity message";
    BOOST_LOG_TRIVIAL(warning) << "A warning severity message";
    BOOST_LOG_TRIVIAL(error) << "An error severity message";
    BOOST_LOG_TRIVIAL(fatal) << "A fatal severity message";

    std::atomic<bool> exiting(false);
    std::vector<std::thread> threads;
    for ( int i = 0; i < 8; ++i ) {
        threads.push_back(std::thread([&exiting](){
            while (!exiting)
                BOOST_LOG_TRIVIAL(trace) << "thread " << std::this_thread::get_id() << " trace";
        }));
    }

    usleep(1000000);
    exiting = true;
    std::for_each(threads.begin(), threads.end(), [](std::thread& t){
        t.join();
    });

    return 0;
}

问题: 使用顶部的命令行,我将使用动态链接进行构建。一切似乎都很好。我看到带有线程 ID 和跟踪信息的明显有效的输出。

但是,在我的项目中,我需要能够使用静态链接。所以我在 g++ 命令中添加了“-static”开关,并注释掉了 BOOST_ALL_DYN_LINK 的#define。它构建得很好。但是当我执行程序时,它会一直运行到第一个线程被创建,然后是段错误。回溯似乎总是一样的:

#0  0x0000000000000000 in ?? ()
#1  0x0000000000402805 in __gthread_equal (__t1=140737354118912, __t2=0) at /usr/include/x86_64-linux-gnu/c++/4.8/bits/gthr-default.h:680
#2  0x0000000000404116 in std::operator== (__x=..., __y=...) at /usr/include/c++/4.8/thread:84
#3  0x0000000000404c03 in std::operator<< <char, std::char_traits<char> > (__out=..., __id=...) at /usr/include/c++/4.8/thread:234
#4  0x000000000040467e in boost::log::v2s_mt_posix::operator<< <char, std::char_traits<char>, std::allocator<char>, std::thread::id> (strm=..., 
    value=...) at /usr/include/boost/log/utility/formatting_ostream.hpp:710
#5  0x0000000000402939 in __lambda0::operator() (__closure=0x7bb5e0) at staticlinktest.cpp:27
#6  0x0000000000403ea8 in std::_Bind_simple<main(int, char**)::__lambda0()>::_M_invoke<>(std::_Index_tuple<>) (this=0x7bb5e0)
    at /usr/include/c++/4.8/functional:1732
#7  0x0000000000403dff in std::_Bind_simple<main(int, char**)::__lambda0()>::operator()(void) (this=0x7bb5e0)
    at /usr/include/c++/4.8/functional:1720
#8  0x0000000000403d98 in std::thread::_Impl<std::_Bind_simple<main(int, char**)::__lambda0()> >::_M_run(void) (this=0x7bb5c8)
    at /usr/include/c++/4.8/thread:115
#9  0x000000000047ce60 in execute_native_thread_routine ()
#10 0x000000000042a962 in start_thread (arg=0x7ffff7ffb700) at pthread_create.c:312
#11 0x00000000004e5ba9 in clone ()

在我看来,它好像在尝试调用空函数指针,并且仅在静态链接时。有什么想法吗?我做错了吗?

【问题讨论】:

  • “GCC 和/或 libstdc++ 中的问题” - 虽然它可能发生,但几乎从来没有发生过。始终首先在您自己的代码中查找问题。
  • 这就是我寻求帮助的原因:)

标签: c++ gcc c++11 pthreads static-linking


【解决方案1】:

libpthread 静态链接到您的应用程序是really bad idea

尽管如此,这里是如何做到这一点的。

我首先修复了编译错误(我怀疑你没有向我们展示你实际编译的代码,或者 boost 对命名空间的污染那么大),然后删除了不相关的 boost 内容,这只会给问题增加噪音.代码如下:

#include <atomic>
#include <chrono>
#include <iostream>
#include <thread>
#include <vector>

int main(int, char*[])
{
    std::atomic<bool> exiting(false);

    std::vector<std::thread> threads;
    for ( int i = 0; i < 8; ++i ) {
        threads.push_back(std::thread([&exiting](){
            while (!exiting)
                std::cout << "thread " << std::this_thread::get_id() << " trace\n";
        }));
    }

    std::this_thread::sleep_for(std::chrono::milliseconds(1));

    exiting = true;

    for(auto& t : threads){
        t.join();
    };

    return 0;
}

如果我动态链接它运行良好,但静态链接时崩溃:

terminate called after throwing an instance of 'std::system_error'
  what():  Operation not permitted
Aborted (core dumped)

根据this e-mail,如果您使用线程静态链接,则必须适当配置libstdc++。以下是使其与静态链接一起使用的神奇标志:

g++ -std=c++11 -pedantic -pthread threads.cpp -static -Wl,--whole-archive -lpthread -Wl,--no-whole-archive

正如我之前所说,将libpthread 静态链接到您的应用程序是自找麻烦。

【讨论】:

  • 问题中的代码实际上是从我发送给同事的文件中复制/粘贴的全部内容,并且在这里编译得很好。尽管如此,很高兴知道将 -lpthread 包装在 --whole-archive 似乎已经成功了。您提到的链接--enable-tls;我认为这需要重建 GCC?
  • @inetknght 是的,不幸的是,这意味着重建 GCC。
  • 我想这也意味着如果我动态链接到 pthreads 也会解决这个崩溃?
  • @inetknght 可能是的,这将是我的第一个猜测。在任何情况下,我都会动态链接 pthread。
猜你喜欢
  • 2014-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-10
相关资源
最近更新 更多