1

c++コードがリリースモードでコンパイルされている場合にのみ発生するある種のメモリまたはwinsockの問題があります。

そのメモリの問題の証拠:

以前の未知のバグは、2行のコードをコメントアウトすることで修正されました。これらの2行のコードは無害に見えます。それらは古いバージョンから残されました。これは、どこかで初期化されていないメモリを使用していることを示しています。XS_Clientは基本クラスとして使用されます。

        class XS_Client
        {
        private:

            /* these two lines of comments fixed the bug */
            /***********************************************
            enum { max_length = 1024 };
            char data_[max_length];
            **********************************************/

            void * context_;
            void * socket_;
            boost::thread t_;
            volatile bool should_run_;              
        public:
            XS_Client(void *context, short type, const std::string &address)
            : context_(context), socket_(XS_Socket::NewSocket(context_,type))
            {
                XS_Socket::Connect(socket_,address);
        #ifdef _OUTPUTD
                std::cout << address << " XS_Client: " << GetCurrentThreadId() << std::endl;
        #endif
                boost::thread   t(boost::bind(&XS_Client::thread_func, this));
                t_.swap(t);
            }

            void SetSockOpt(int option, const void *optval,size_t optvallen)
            {
                int rc = xs_setsockopt(socket_,option,optval,optvallen);
                if ( rc != 0 )
                    std::cout << "xs_setsockopt error: " << xs_strerror(errno) << std::endl;
            }

            virtual ~XS_Client()
            {
                if ( should_run_ )
                    Stop();
            }

            void thread_func() {
                /* Create an empty message */
                xs_msg_t msg;

                while (should_run_)
                {
                    //int bytes_recvd = xs_recv(socket_,data_,max_length,0);
                    int rc = xs_msg_init (&msg);
                    if ( rc != 0 )
                        std::cout << "xs_msg_init error: " << xs_strerror(errno) << std::endl;
                    assert (rc == 0);
                    /* Block until a message is available to be received from socket */
                    int bytes_recvd = xs_recvmsg (socket_, &msg, 0);

        #ifdef _DEBUG 
                    std::cout << "received " << bytes_recvd << std::endl;
        #endif;

                    if ( bytes_recvd == -1 )
                    {

                        if ( xs_errno() == ETERM ) 
                        {
                            should_run_ = false;
                            std::cout << "ETERM received" << xs_strerror(errno) << std::endl;
                            break;
                        }

                        if ( !should_run_ )
                            xs_msg_close (&msg);
                        else
                        {
                            std::cout << "receive error!" << xs_strerror(errno) << std::endl;
                            boost::this_thread::sleep(boost::posix_time::milliseconds(100u));
                        }
                    }
                    else 
                    {

        #ifdef _DEBUG 
                        //std::cout << "received " << xs_msg_data(&msg) << std::endl;
        #endif;
                        OnMsg(xs_msg_data(&msg),bytes_recvd);

                        /* Release message */
                        xs_msg_close (&msg);
                    }

                }

                int rc = xs_close (socket_);        
                if ( rc != 0 )
                    std::cout << "xs_close error: " << xs_strerror(errno) << std::endl;

                Cleanup();
            }

            virtual void OnMsg(const void *msg, int bytes_recvd)
            {
                std::cout << "virtual void OnMsg received " << bytes_recvd << std::endl;
            }

            virtual void Stop()
            {
                should_run_ = false;
                t_.timed_join(boost::posix_time::milliseconds(2000));
            }

            virtual void Cleanup()
            {
            }


        };

そのウィンドウ/ソケットの問題の証拠:

本当のバグは、私のtcpソケット(localhost)がデータを取得しないことです。ただし、これは、同じプロセスでboost::asioとcrossroads/0mqの両方を使用している場合にのみ発生します。また、デバッガーで処理を開始してもバグは発生しません。

したがって、「realesewithdebuginfo」モードでコンパイルすると、デバッガーにない場合にのみバグが発生します。同じ正確にコンパイルされたコード。

質問1:C++コード分析やWindowsAPI呼び出し分析に推奨されるツールは何ですか?また、問題は簡単に再現できないため、静的分析が最適な場合があります。私はたくさんのテンプレート、boost :: asio :: udp、複数のトレッドライブラリを使用しています。複数のsocket/ioライブラリ。

質問2:外部ライブラリによるソケットの誤用が原因でデッドロックが発生しているかどうかを確認するために、Windows側で何を利用できますか?

tyvm4yh

4

1 に答える 1

2

デバッガーで実行する場合とそうでない場合の主な違いは、デバッグヒープです。_NO_DEBUG_HEAPデバッグヒープをオフに切り替えるには、環境変数を使用できます。これはグローバルに設定できますが、次の回答のように、デバッグの実行のためだけに設定する方がはるかに優れています。

https://stackoverflow.com/a/1060929/1618406

これでバグが再現されても、(コードが最適化されているために)実際にデバッグするのが難しい場合は、リリースビルドの最適化を一時的に無効にします。それらを再びオンにすることを忘れないでください...

ほぼ毎回、デバッグヒープをオフにし、最適化を無効にすることで、この種のバグをデバッガーで再現し、それほど面倒なことなくデバッグできるようになりました。

さらに、Windows 7を使用している場合は、プログラム互換性アシスタントが介入して、プログラムを機能させる何かを実行していることに気付くかもしれません。

http://www.virtualdub.org/blog/pivot/entry.php?id=319

プログラムのマニフェストでこれを無効にできると思われますが、グループポリシーエディターを使用して無効にすることをお勧めします。例:

http://www.howtogeek.com/howto/4161/disable-program-compatibility-assistant-in-windows-7-and-vista/

デバッガの外部でプログラムを実行する場合は、プログラム互換性アシスタントを無効にすることを強くお勧めします...

于 2012-10-15T16:30:18.447 に答える