使用静态链接启动std :: thread会导致分段错误

and*_*ker 11 c++ c++11

要学习c ++ 11(和boost)我正在使用boost asio和c ++ 11(用于线程和lambdas)编写一个简单的http服务器.

我想测试新的c ++ 11 lambdas和std :: thread,所以我尝试io_service.run()在带有lambda的std :: thread中启动这样的:

#include <iostream>
#include <thread>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
using std::cout;
using std::endl;
using boost::asio::ip::tcp;

class HttpServer
{
public:
    HttpServer(std::size_t thread_pool_size)
    : io_service_(),
    endpoint_(boost::asio::ip::tcp::v4(), 8000),
    acceptor_(io_service_, endpoint_)
    { }

    void Start() {
        acceptor_.listen();
        cout << "Adr before " << &io_service_ << endl;
        std::thread io_thread([this](){
            cout << "Adr inside " << &io_service_ << endl;
            io_service_.run();
        });
        io_thread.join();
    }

private:
    boost::asio::io_service io_service_;
    tcp::endpoint endpoint_;
    tcp::acceptor acceptor_;
};

int main() {
    HttpServer server(2);
    server.Start();
}
Run Code Online (Sandbox Code Playgroud)

这终止于分段错误.另外,有时候它会在lambda中运行cout,有时候不会(尽管endl应该刷新).在任何情况下,它打印正确的地址io_service_.但是,当我std::thread用a 替换boost::thread(没有其他更改!)时,一切正常.

如果有人知道导致问题的原因(可能是asio,std :: thread或std :: lambda),我将不胜感激.

附加信息:

根据另一篇文章,访问成员io_service_在lambda中捕获时很好this,正如我所做的那样.

我在Ubuntu上运行gcc 4.6.1并提升1.46.G ++参数:

g++ -std=c++0x -static -I/home/andre/DEV/boost_1_48_0/include/ -L/home/andre/DEV/boost_1_48_0/lib/ -o webserver main.cpp -lboost_system -lboost_thread -lpthread
Run Code Online (Sandbox Code Playgroud)

更新:

删除-static修复了问题.我发现问题与boost或lambdas无关,并且可以在构建静态和使用时重现std::thread.出于任何原因,这种组合不起作用.我认为这篇文章描述的几乎相同,但我并不真正理解细节,错误信息也不同.

所以我想知道为什么std::thread和静态链接似乎不能一起工作.这里有不允许静态链接的原因吗?我更新了问题标题并删除了升级标记.

小智 9

将您的应用与-Wl,--whole-archive -lpthread -Wl,--no-whole-archive 更多链接联系起来https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52590 它适合我.

  • 令人遗憾的是,即使在gcc 6.2中,仅与`-static -pthread`链接的结果也会导致可执行文件损坏(即运行时错误),并且没有链接器错误甚至警告.我不得不花几个小时进行调试才发现自gcc 4.7以来已知问题,并被解析为"已解决的无效".你的回答终于指出了我做错了什么. (2认同)
  • 对于来到这里并想知道的人来说,是的,这在 2020 年 GCC 10 中仍然是必要的。 (2认同)

and*_*ker 6

删除-static解决了这个问题.我发现它与boost或lambdas没有任何关系,但是使用静态链接std::thread,并且由于任何未知原因似乎无法协同工作(另请参阅此帖子可能相关).

我猜他们为什么不能一起工作的问题 - 虽然很有趣 - 现在已超出范围,我很高兴答案,所以这可以标记为已回答.