More on the socket server VS2005 "leaks"

| 4 Comments

A while ago I reported that I'd been seeing very strange memory usage patterns in the debug build of the simple echo server when built with Visual Studio 2005 using the standard version of STL that ships with it. The thing that interests me most about this leak is that it seems to be more of a 'strange allocation strategy' rather than a leak as I was previously able to get the memory usage to grow to a large amount and then suddenly it dropped back to something reasonable and then started to grow again. The other interesting thing is that it doesn't exist if I build with STLPort.

Today I've finally had some time to build and test the server properly and I'm pretty sure that I've found the location of the leak. In the next few days I hope to release a new build of the servers (using the existing freely available codebase) but including the couple of changes required to get the code to build with VS2005 and the bug fixes that I've mentioned in the comments to the original postings. This will be the final (I hope) release of this code.

The leak occurs in this code:

template <class T>
_tstring ToString(T num)
{
   _tstring strNum = _T("");
   
   {
      std::strstream buf;

buf << num << std::ends; #ifdef _UNICODE std::string temp = buf.str(); USES_CONVERSION; strNum = A2W(temp.c_str()); #else strNum = buf.str(); #endif buf.freeze(false); } return strNum; }

If I comment out the body of the method and just return an empty string then the leak vanishes. The location of the leak explains why the debug build leaks so much more than the release build; the debug build calls this function to convert the current thread id to a string every time it outputs a debug log line, and in the release build the debug log code doesn't exist.

The fact that the leak occurs in all builds, unicode and non-unicode means we can discard any thoughts of the narrow to wide string conversion code being at fault. Having traced through the code it looks like I'm not abusing the STL; I've yet to check my references but calling str() on a strstream gives the caller ownership of the buffer within the strstream and calling freeze(false) gives it back to the strstream. Tracing through a single call shows that the buffer is correctly destroyed when the strstream goes out of scope.

More investigation is needed but I'm quite pleased to have located the leak...

4 Comments

I've now got a minimal reproduction of this problem... It only leaks on VS2005 with the native STL, VC6 through 2003 are fine as is VS2005 with STLPort. Interestingly it seems to go away if I use an ostrstream rather than a strstream... Which is handy because I only really need an ostrstream...

After spending some quality time with Josuttis' The C++ Standard Library I decided to try a switch to a stringstream and, amusingly, that leaks on VS2005 too... Ho hum, more debugging when I'm less tired methinks...

I know this is fairly old, but I happened to come across it and recognize a problem I had. This line:

buf << num << std::ends;

causes the buffer to tack on a null terminator, and naturally to increment the length. When you call str() (in a debug version, using VS2003, at least) the resulting string considers this null terminator part of the string and adds another. The string operations don't seem to handle this well, and appending anything to that string appears to have no effect because it leaves a null terminator in the middle of the string. I fixed this by simply removing the "<< ends"

It's been a while since I ran into that particular issue, and I have no idea whether it's related, but it might be. Hopefully I described it clearly.

Tim,

That's interesting. Are you suggesting that adding std::ends results in different behaviour in VS2003 than in other versions of visual studio or simply that there's actually no need to add std::ends at all, ever?

I don't think it's related to the leak I had as I managed to locate a knowledge base article on the leak (see the next posting!).

Leave a comment