Closing Sockets and Avoiding Resource Leaks
If you forget to close a socket using closesocket(), then its resources remain in use by the system. Resource leaks, like memory leaks, can lead to subtle bugs, as shown in the following code.
try {
RWSocket s;
s.connect( RWInetAddr(3010,"net.roguewave.com") );
s.sendAtLeast( "hi Bob" ); //1
s.closesocket(); //2
}
catch (const RWxmsg& x) { //3
// Handle error here
}
If the call to sendAtLeast() on line //1 fails, an exception is thrown and caught by the exception handler on line //3, and the socket is never closed. Because of the exception, the call to closesocket() on line //2 is skipped.
NOTE: The
RWSocket class does not use the “resource acquisition is initialization” technique described by Stroustrup in “The C++ Programming Language.” In this technique, freeing a resource—closing a socket—is done by a destructor. The destructor for
RWSocket, however, does not close the underlying socket. You are responsible for writing code that closes each socket exactly once.
RWSocket is a low-level class and wraps Berkeley sockets thinly. It does not prohibit code such as the following:
RWSocket getSocket()
{
RWSocket s;
.
.// Connect the socket s
.
return s; //1
}
If the
RWSocket destructor executed at line
//1 closes the socket, the
RWSocket returned by the function cannot be used. Because
RWSocket is a thin wrapper over sockets,
RWSocket does not know about the existence of copies. This means that the destructor cannot selectively close the socket, leaving it open if more copies of the socket are in use. Also, legacy C code might hold a C representation of the socket. Such code would not run correctly if the C++ destructor closed the socket.