boost :: system :: error_code :: message()使用boost :: asio socket抛出访问冲突异常

mat*_*975 4 c++ multithreading boost-asio c++builder-xe4

我正在实现一个客户端应用程序,它必须与硬件设备建立少量套接字连接.我已将问题分解为以下小代码子集

boost::system::error_code ec;
std::string str_message = ec.message();  // no access violation before connect()
std::string str_port = "502";
std::string str_ip = "192.168.12.198";

boost::asio::io_service io_service;
boost::asio::ip::tcp::resolver resolver(io_service);
boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(),str_ip,str_port);
boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query);
boost::asio::ip::tcp::socket s(io_service);

ec = s.connect(*iterator,ec);
if (ec)
{
    // connection error of some kind.
    std::string str_debug = ec.message();  // BANG!!!!

}
Run Code Online (Sandbox Code Playgroud)

我正在使用Embarcadero RAD studio XE4 C++ Builder,当我在主VCL线程中运行上面的代码时,它运行正常.当我和多个连接运行它,我上面的代码中的多个实例运行TThread类,这是当我进入访问冲突的问题-它似乎是,当error_code被修改的connect电话,该内部构件m_cat中的error_code实例变为NULL,所以当我打电话时,message()我得到访问冲突.即使我只运行一个后台线程,也会发生这种情况.

上面的代码是否有可能在我需要使用它的方式上不是线程安全的?我试图找出为什么这个代码不会在后台线程中运行,但找不到任何关于它的东西.

我运行的升级版本是1.50,因为这是用于在RAD studio中构建64位应用程序的集成版本.

是否有其他人在多线程设置(Embarcadero或其他)中遇到此问题,如果是这样,你是如何解决它的?或者这个类是不安全的以多线程方式使用?

Com*_*sMS 5

这是一个很长的镜头,但它可能值得一试:

system::error_code由两个入口:一个误差值和一个类别.错误值基本上只是一个int,但类别是Singleton.这是必需的,因为基于指针标识比较错误类别的相等性(即,当且仅当它们指向相同的类别对象时,两个类别相等).

问题是Singleton类别的初始化可能不是线程安全的.Asio使用的system_category是实现的boost/libs/system/src/error_code.cpp.对于1.50,实现看起来像这样:

BOOST_SYSTEM_DECL const error_category & system_category() BOOST_SYSTEM_NOEXCEPT
{
  static const system_error_category  system_category_const;
  return system_category_const;
}
Run Code Online (Sandbox Code Playgroud)

这保证在符合C++ 11的编译器上是线程安全的,但是如果你的编译器没有实现函数范围静态的线程安全初始化,那么这可能会破坏.您可以通过跟踪对此功能的调用轻松验证这一点,看看您是否观察到了潜在的竞争.


Syl*_*Syl 1

在多个示例中,他们在线程中调用 io_service->run(): http ://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/example/cpp11/futures/daytime_client.cpp

我喜欢这个,有一个线程池: Thread pool using boost asio

您确定 io_service->run() 在某个地方被调用了吗?