2017-11-06 15 views
0

私のasioベースのアプリケーションでは、エラー処理に問題があります。 async_read/async_write関数でasio single-threaded/single io_serviceを使用し、完了ハンドラで渡されたエラーコードがnullでない場合、エラーが発生したため、その.message()メソッドを呼び出すとsegfaultが発生します。 -categoryポインタがnullを指しています。ただし、実際の値は常に正しいです。boost asioエラーカテゴリがnullです

奇妙なことに、これはテストアプリケーションでは再現できません。これは私がやっている本質的であるが、エラーの場合は、期待通りにここにメッセージを()を呼び出すと、動作します。私はそれは私のアプリケーションの寿命の問題ではないと思います

void do_write(std::shared_ptr<std::vector<unsigned char>> , std::shared_ptr<boost::asio::ip::tcp::socket>); 

void do_read(std::shared_ptr<std::vector<unsigned char>> buf, std::shared_ptr<boost::asio::ip::tcp::socket> sock) 
{ 
    boost::asio::async_read(*sock, boost::asio::buffer(*buf), boost::asio::transfer_exactly(100000), 
          [sock, buf](const boost::system::error_code& ec, std::size_t bytes) 
    { 
     std::cout << "read\n"; 
     if (ec) { 
     std::cout << ec.message() << std::flush; 
     } else { 
     do_write(buf, sock); 
     } 
    }); 
} 

void do_write(std::shared_ptr<std::vector<unsigned char>> buf, std::shared_ptr<boost::asio::ip::tcp::socket> sock) 
{ 
    boost::asio::async_write(*sock, boost::asio::buffer(*buf), [sock, buf](const boost::system::error_code& ec, std::size_t bytes) 
    { 
     std::cout << "write\n"; 
     if (ec) { 
     std::cout << ec.message() << std::flush; 
     } else { 
     do_read(buf, sock); 
     } 
    }); 
} 

int main() 
{ 
    auto buf = std::make_shared<std::vector<unsigned char>>(100000); 

    unsigned short port = 1113; 
    boost::asio::io_service ios; 
    boost::asio::ip::tcp::acceptor acptr {ios, boost::asio::ip::tcp::endpoint{boost::asio::ip::tcp::v4(), port}}; 

    auto socket = std::make_shared<boost::asio::ip::tcp::socket>(acptr.get_io_service()); 
    acptr.async_accept(*socket, [socket, buf](const boost::system::error_code& ec) 
    { 
     do_read(buf, socket); 
    }); 
    ios.run(); 
} 

、AddressSanitizerは見つけられません。潜在的なエラーと私は何の問題もなく何百メガバイトのデータをシフトすることができます。また、message()の呼び出しをコメント解除するだけで、サーバーは正常に動作し続け、新しい接続を正しく処理します。とにかく、クラッシュが発生したときのコールスタックは次のようになります。

https://gist.github.com/mariusherzog/82f24caf9eea4d94946706aa8c025ef1 カテゴリはフレーム11からヌルを指しています。

私は、私は考えることができる唯一のことは、今のコードの一部は、グローバル静的データを構築の一環として初期化していることで打ち鳴らす3.9.1とgcc 5.4.0

答えて

1

とブースト1.62でのLinuxを使用しています。その時点でカテゴリ参照を取得し、複数の翻訳単位がある場合、カテゴリインスタンスはまだ構築されていない可能性があります。

この状況は、Static Initialization Order Fiascoとよく言われています。それ以外


、逆は(グローバルカテゴリが破壊された)頭に浮かぶ。なぜなら、シャットダウン時に発生することを認識していたからです。このようなシナリオでは、参照は通常nullにならない可能性があります。

+0

ありがとうございます。エラーカテゴリ(get_misc_category)はMeyerのシングルトンを介してアクセスされます。ブレークポイントをそこに置くと、実際のインスタンスは最初からメモリ内ですべてnullになります。これはasioのバグでしょうか? –

+0

また、私のアプリケーションでは複数回呼び出されていますが、一見異なる翻訳単位が原因です... –

+0

Meyerのシングルトン経由でアクセスするかどうかは重要ではありません:もっと重要なのは、 'get_misc_category()' ***です** *それ自体はマイヤーのシングルトンです。それが間違っている場合、間違っていると私が実際に想像することができるのは、実行時リンクです。 – sehe

関連する問題