This is - from a pure problem-solving standpoint - is a solved problem but the underlying mechanism might be interesting to some, including me.
I wrote a pretty basic server, listening on a given TCP port. I wrote it in a way, that it can accept multiple requests, not just one and exit, with a while loop.
Since I'm not experienced in C++, I googled a solution and fabricated it to my needs. The part of the code in question looks like this:
socklen_t addrlen = sizeof(address);
while(true) {
try {
std::cerr << "Listening..." << std::endl;
if(listen(socketId, 3) < 0) {
std::cerr << "Error while listening for incoming connections" << std::endl;
throw;
}
processRequest(accept(socketId, (struct sockaddr *) &address, &addrlen));
} catch(Json::RuntimeError& e) {
std::cerr << "Json error: " << e.what() << std::endl;
} catch(...) {
std::cerr << "Unknown error" << std::endl;
throw;
}
}
The problem with this code is tricky and might be obvious to the more experienced ones of you, but it definitely isn't obvious to me.
I show you a part of the class definition:
int socketId;
sockaddr_in address;
const RequestProcessor& processor;
Notice the order of these variables.
With the method above and the variables in this order, the first request runs smoothly and the software starts listening for the next request as it's intended to.
However, when the second request arrives, the processor reference gets overwritten, presumably because there is some memory overflow - or whatever it's called - happening, which rewrites the memory location the processor reference points to, causing an error somewhere down the line in a method not shown here.
The solution is easy, but can be really hard to find out:
while(true) {
try {
std::cerr << "Listening..." << std::endl;
if(listen(socketId, 3) < 0) {
std::cerr << "Error while listening for incoming connections" << std::endl;
throw;
}
socklen_t addrlen = sizeof(address);
processRequest(accept(socketId, (struct sockaddr *) &address, &addrlen));
} catch(Json::RuntimeError& e) {
std::cerr << "Json error: " << e.what() << std::endl;
} catch(...) {
std::cerr << "Unknown error" << std::endl;
throw;
}
}
All I did was replace where the addrlen variable is created. This solves the problem and has an added benefit, of being more "reasonable looking".
The question is: why moving the initialization of addrlen solve this problem?