1

我有某种内存或 Winsock 问题,仅在 C++ 代码在发布模式下编译时才会出现。

证明它是内存问题的证据:

通过注释掉两行代码,修复了以前的未知错误。这两行代码似乎无害。它们是旧版本的遗留物。这表明我在某个地方使用了未初始化的内存。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()
            {
            }


        };

证明它是 Windows/socket 问题的证据:

真正的错误是我的 tcp 套接字 (localhost) 永远不会获取数据。然而,这只发生在我在同一进程中同时使用 boost::asio 和 crossroads/0mq 时。此外,如果我通过调试器启动该过程,则不会发生该错误。

因此,当我在“realesewithdebuginfo”模式下编译时,该错误仅在不在调试器中时出现。完全相同的编译代码。

问题1:c++代码分析和/或windows api调用分析推荐什么工具?此外,问题不容易重现,因此最好进行静态分析。我使用了很多模板,boost::asio::udp,多个踩库。多个套接字/io 库。

问题2:在windows端有什么可以查看我是否由于外部库的socket i/o mis-us-sages而导致死锁?

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 回答