I have having some sort of memory or winsock issue that only occurs when c++ code is compiled in release mode.
Evidence that its a memory issue:
A previous unknown bug was fixed, by commenting out two lines of code. These two lines of code seem harmless. they were left overs from old versions. This indicates that somewhere I am using un-initialized memory. XS_Client is used as a base class.
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()
{
}
};
Evidence that its a windows/socket issue:
The real bug is that my tcp socket (localhost) never gets data. However this only occurs when I am using both boost::asio and crossroads/0mq in same process. Also, the bug does not occur if I start the process through the debugger.
So when I compile in “realesewithdebuginfo” mode the bug only occurs when not in the debugger. same exact compiled code.
question1: what tool is recommended for c++ code analysis and/or windows api call analysis? Also, the problem is not easily recreated, so a static analysis may be best. i use lots of templates, boost::asio::udp, multiple treading libraries. multiple socket/io libraries.
question2: what is available on the windows side to see if I am causing a deadlock due to socket i/o mis-us-sages by external libraries?
tyvm4yh
The main difference between running under a debugger and not is the debug heap. To switch the debug heap off, you can use the
_NO_DEBUG_HEAPenvironment variable. You can set this globally, but you’re much better off doing it just for your debugging runs, as in this answer:https://stackoverflow.com/a/1060929/1618406
If this reproduces the bug, but you’re having difficulty actually debugging (because of the optimised code), I’d just temporarily disable optimisations for your release build. Just don’t forget to switch them back on again…
Pretty much every time, switching the debug heap off and disabling optimisations has let me reproduce this kind of bug in the debugger, and then debug it without too much hassle.
Additionally, if you use Windows 7, you may find the Program Compatibility Assistant is stepping in and doing something that makes your program work, even though it shouldn’t:
http://www.virtualdub.org/blog/pivot/entry.php?id=319
You can supposedly disable this in your program’s manifest, but I prefer to have it disabled using the Group Policy Editor, e.g.:
http://www.howtogeek.com/howto/4161/disable-program-compatibility-assistant-in-windows-7-and-vista/
Disabling the Program Compatibility Assistant is highly recommended if you ever run your program outside the debugger…