Solved program works when built in Debug, not in Release
-
Hi all -
I have a program that runs fine when built in debug mode. When built in profile or release, however, it hangs, apparently on this instruction:
m_sock->connectToHost(ui->lineEditAddr->text(), (quint16) ui->lineEditPort->text().toInt(), QIODevice::ReadWrite, QAbstractSocket::IPv4Protocol); qDebug() << "sockConnect(): returned from connectToHost().";
(The qDebug line is never reached when built in profile or release mode.)
I've had similar problems in the past, but that was a long time ago. What's the checklist for chasing down an oddity like this?
Thanks...
-
Hi,
Might be silly but are you sure you have the correct values as parameters ?
One thing I would modify is the port line edit, just use a QSpinBox, it will avoid input mistakes.
-
@SGaist not silly at all, but what parameter values are you talking about?
-
The address and port used.
You can also use something like Wireshark to check what is going on on the network side.
-
Oh yeah, those are good. (At least I'm entering the same values as I am when I run in debug.) I'm fairly confident that isn't the issue; it's probably more like some step I'm overlooking for configuring the release build.
-
Hence the use of Wireshark, you should at least see the connection being made.
-
@mzimmers out of curiosity, did you do a connect to the Error-Signal of the QAbstractSocket and is it triggered ? At the very least you should get a timeout-error after some time (30 seconds I believe)
-
@mzimmers said in program works when built in Debug, not in Release:
I'm fairly confident that isn't the issue
A dangerous assumption :-)
-
Are you running from Visual Studio? Once I got stuck for days because the Path set in the Environment was different for Debug and Release. (Project properties -> Debugging -> Environment)
-
J.Hilk: yes, I've connected the error signal, and it doesn't trigger -- probably because the call to connectToHost() hangs before it gets a chance to send that signal.
jsulm: agreed, but the only two arguments in this case are the IP address and the port number. Besides, even if they're wrong, I should get a connection error, not a hang.
JoZCaVaLLo: no, I'm not using VS. I'm running the program from Creator.
-
I'd make sure all pointers are correct at this line:
m_sock
,ui->lineEditAddr
,ui->lineEditPort
.Also, did you add a qDebug() before the statement so make sure it is reached?
And just to make sure, you pass an IP address, not a host name, right?
-
-
Thanks for all the suggestions, guys. I found the problem (though I don't fully understand it) -- I had an uninitialized member variable that was used to hold the socket state. When built in release mode, this variable happened to be assigned a random number (a very large one) that somehow caused this code to malfunction:
void Widget::sockConnect() { while (m_socketState != QAbstractSocket::UnconnectedState) { cout << "m_socketState is " << m_socketState << endl; m_sock->disconnectFromHost(); QThread::msleep(10); }
I only got the output of the cout once, and then the program hung. Maybe the disconnectFromHost() call hangs if you're not connected?
ADDED:
Regarding Wireshark: I'm running on a Windows 10 machine. Wireshark has the odd behavior of not showing packets unless/until they're acknowledged. This may be due to some setting somewhere, but I can't find it, and it greatly diminishes Wireshark's value for troubleshooting this kind of problem.
-
@mzimmers
to be honest, uninitialized members are 90% of the time the cause for such errors. Debug builds do a lot of stuff behind the scene, most importandly for this case, init pointers as nullptrs.
Release builds donโtBut from the code example, there was no indication this would be the problem,
great you could find the issue -
@J.Hilk said in program works when built in Debug, not in Release:
Debug builds do a lot of stuff behind the scene, most importandly for this case, init pointers as nullptrs.
They do not, it's just rotten luck that it happened this part of the memory was holding zeroes in debug.
@mzimmers said in program works when built in Debug, not in Release:
Thanks for all the suggestions, guys. I found the problem (though I don't fully understand it) -- I had an uninitialized member variable that was used to hold the socket state.
A small anecdote if you'll allow me:
When I was learning to program some 15 years ago I had been struggling with some exercise from a C book. Now, many books don't really take much time to explain discipline, so I had been at it for a day or two and getting my hair pulled out trying to figure out what was going wrong. I asked my dad for advice (he's a programmer). He didn't even look at the code, what he said basically boiled down to:
"Format your code properly. Always initialize variables when you declare them, even if it seems pointless. Use the debugger to trace down runtime problems."There are two things to take away from this:
- Be clean about your code, meticulous - never leave loose ends, also in formatting. This includes notably having everything defined and your intent very clear. Clean up after yourself when the program shuts down (even if it shuts down abnormally, clean as much as possible).
- Building in release with debug information is your friend in those cases. True, you won't be able to step into code easily, but you're going to get meaningful stack traces. If everything else fails inspecting the assembly can be helpful.
These little things have served me very well through the years, so I always try to advise people likewise.
-
"Format your code properly. Always initialize variables when you declare them, even if it seems pointless. Use the debugger to trace down runtime problems."
So true!
I like the "always init your variables" part especially. C++11 allows us to init member variables inplace, thats a really great tool I recommend everyone.
-
@kshegunov said in program works when built in Debug, not in Release:
They do not, it's just rotten luck that it happened this part of the memory was holding zeroes in debug.
I think you'r wrong about that,
take this example.
int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); int b; int *pA; qDebug() << b << pA; return a.exec(); }
gives a consistent output of 0 and 0x0 when build and run in debug. But total random numbers on release build.
Using clang in my case. -
@J.Hilk said in program works when built in Debug, not in Release:
I think you'r wrong about that,
It's been known to happen, but you will need to open the assembly and show me where is this code that sets the variables to zero ... I'm also stubborn that way.
gives a consistent output of 0 and 0x0 when build and run in debug.
First run with g++, just for kicks:
21845 0x5555555553c0
I'd point you to read about the Monte Carlo fallacy. :)
-
@kshegunov
Iโm way ro lazy to do much more, I usually initialise my variables ๐.But I yield to your experience, 15 years is a bit more than I have ๐
-
@J.Hilk said in program works when built in Debug, not in Release:
But I yield to your experience, 15 years is a bit more than I have
"Don't" is the best advice I can give you. Experience != being right, although they do correlate. ;)