簡體   English   中英

boost :: system :: error_code :: message()使用boost :: asio socket拋出訪問沖突異常

[英]boost::system::error_code::message() throwing access violation exception with boost::asio socket

我正在實現一個客戶端應用程序,它必須與硬件設備建立少量套接字連接。 我已將問題分解為以下小代碼子集

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!!!!

}

我正在使用Embarcadero RAD studio XE4 C ++ Builder,當我在主VCL線程中運行上面的代碼時,它運行正常。 當我使用多個連接運行它時,我在TThread類的多個實例中運行上面的代碼,這是當我遇到訪問沖突的問題時 - 看來當connect調用修改error_code時,內部成員error_code實例的m_cat變為NULL,所以當我調用message()我得到訪問沖突。 即使我只運行一個后台線程,也會發生這種情況。

上面的代碼是否有可能在我需要使用它的方式上不是線程安全的? 我試圖找出為什么這個代碼不會在后台線程中運行,但找不到任何關於它的東西。

我運行的升級版本是1.50,因為這是用於在RAD studio中構建64位應用程序的集成版本。

有沒有其他人在多線程設置中遇到此問題(在Embarcadero或其他方面),如果是這樣,你是如何解決它的? 或者這個類是不安全的以多線程方式使用?

這是一個很長的鏡頭,但它可能值得一試:

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;
}

這保證在符合C ++ 11的編譯器上是線程安全的,但是如果你的編譯器沒有實現函數范圍靜態的線程安全初始化 ,那么這可能會破壞。 您可以通過跟蹤對此功能的調用輕松驗證這一點,看看您是否觀察到了潛在的競爭。

在多個示例中,他們在一個線程中調用io_service-> run(): http//www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/example/cpp11/futures/daytime_client.cpp

我喜歡這個,使用了一個ThreadPool: 使用boost asio的線程池

你確定在某處調用了io_service-> run()嗎?

你必須始終確保iterator != boost::asio::ip::tcp::resolver::iterator()

來自boost docs:

默認構造的迭代器表示列表的結尾。

我敢打賭這是問題, connect()只是因為無效的端點迭代器而破壞了堆棧。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM