Jump to content
  • Advertisement
Sign in to follow this  
Illco

Leak in std::stringstream on MSVC?

This topic is 4842 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

After three years it is finally here: my first question post. I hope someone knows the answer to this. I found a memory leak in my engine and narrowed it down to the use of std::stringstream. This is a part of STL I seldomly use so perhaps I am doing something wrong. I created a test program under MS VC 6.0 (SP6) which is as follows:
#include <crtdbg.h>
#include <sstream>

void f( void )
{
	std::stringstream ss;
}

void main( void )
{
	f();	

	_CrtDumpMemoryLeaks();
}

Note I put the stringstream in f() to prevent the leak tracer to report something that gets deleted only at the end of main(). This reports two memory leaks as follows:
Detected memory leaks!
Dumping objects ->
{45} normal block at 0x003207B8, 33 bytes long.
 Data: < C              > 00 43 00 CD CD CD CD CD CD CD CD CD CD CD CD CD 
{44} normal block at 0x00322FA8, 40 bytes long.
 Data: <  B             > 98 B1 42 00 04 00 00 00 00 00 00 00 00 00 00 00 
Object dump complete.
Is there something I must do to destroy a standard stringstream? Is this a known but undocumented issue with MS's STL implementation? Pleas let me know. Greetz, Illco

Share this post


Link to post
Share on other sites
Advertisement
Quote:
Original post by Illco
Is there something I must do to destroy a standard stringstream?


No as its allocated on the stack the destructor is invoked at the end of "f"'s scope automatically.

Quote:
Original post by Illco
Is this a known but undocumented issue with MS's STL implementation? Pleas let me know.


I wouldn't be surprised as VC++ 6.0 has terrible C++ standard compliance (even with service packs applied) and is known to have a poor implementation of the C++ standard library. You should not be using VC++ 6.0's compiler anymore period. I suggest if you must have an MS C++ compiler you either get VC++ 7.1 toolkit (its free, no IDE but you can hook it up to VC++ 6.0 IDE) or use VC++ 8.0 beta 2 (which comes with an IDE).

I tested that code on both VC++ 7.1 & 8.0, no leaks detected as expectated.

Share this post


Link to post
Share on other sites
Quote:

No as its allocated on the stack the destructor is invoked at the end of "f"'s scope automatically.

That's what I thought. Ok. I just wanted to know my code is correct. So I think we can conclude we have a bug here.

Quote:

I wouldn't be surprised as VC++ 6.0 has terrible C++ standard compliance (even with service packs applied) and is known to have a poor implementation of the C++ standard library. You should not be using VC++ 6.0's compiler anymore period.

I knew that -- perhaps time for STLPort or something. Yes I know it is old but the choice to switch over is not free of costs so we will have to stick with it for a while.


Share this post


Link to post
Share on other sites
Quote:
Original post by Illco
I knew that -- perhaps time for STLPort or something. Yes I know it is old but the choice to switch over is not free of costs so we will have to stick with it for a while.


If you can't use another compiler then getting STLport i think would definitely be the way to go.

Share this post


Link to post
Share on other sites
I wouldn't be so quick to dismiss it as a bug. It's quite likely that they're using a pool allocator for small strings (like empty ones) so that when the string stream is destroyed, the allocated string is returned to the pool rather than to the system. This would show up as a 'leak' in this case.

Share this post


Link to post
Share on other sites
it is not a Bug you fool. the Destructor for get called after the _CrtMemCheck. I used to have that problem too and if you want to see if there is no leak. create an Pointer of the list Object Instead and delete the Pointer before calling _CrtMemCheck so the destructor get called first then you will see that you have no leak.

Share this post


Link to post
Share on other sites
Quote:
Original post by BornToCode
it is not a Bug you fool. the Destructor for get called after the _CrtMemCheck.


If you actually looked at the code the std::basic_stringstream's destructor will be invoked at the end of the function "f"'s scope so therefore its called before _CrtMemCheck.

I think Dean Harding maybe wright here but then that would be slightly odd as first its most likely that std::basic_stringstream's stream buffer has std::basic_string as data member and doesn't need to allocate it on the heap secondly the default allocator type std::allocator (which type aliases std::stringstream & std::string use) generally does no pooling but rather uses operator new/delete for allocation/deallocation unless in VC++ 6.0's case it is using another custom allocator type.

Share this post


Link to post
Share on other sites
Quote:

It is not a Bug you fool.

Don't be so quick about calling someone else a fool. If you, beside the code, had read the post you would have seen this is exactly why I added a function f().

Dean and snk_kid: thank you. But what do I do about it to fix such behaviour (besides switching compilers etc.)?

Share this post


Link to post
Share on other sites
Quote:
Original post by snk_kid
I think Dean Harding maybe wright here but then that would be slightly odd as first its most likely that std::basic_stringstream's stream buffer has std::basic_string as data member and doesn't need to allocate it on the heap secondly the default allocator type std::allocator (which type aliases std::stringstream & std::string use) generally does no pooling but rather uses operator new/delete for allocation/deallocation unless in VC++ 6.0's case it is using another custom allocator type.


Yeah, I'm not sure what it uses in VC6. I know in 2002/2003 they use a different std::basic_string which allocates strings < 16 characters on the stack, so that could explain why you don't see it in those compilers.

A simple way to see if I'm right or not is to call f() in a loop and see if the number of 'leaked' blocks stays small. Like this:


#include <crtdbg.h>
#include <sstream>

void f( void )
{
std::stringstream ss;
}

void main( void )
{
for(int i = 0; i < 10000; i++)
f();

_CrtDumpMemoryLeaks();
}



If the number of 'leaked' blocks is small (I'd expect there to be only 1 still) then you don't need to worry, as it's not really a 'leak' as such - the memory is just sitting in a pool, waiting for the next time you allocate one.

Share this post


Link to post
Share on other sites
Quote:

If the number of 'leaked' blocks is small (I'd expect there to be only 1 still) then you don't need to worry, as it's not really a 'leak' as such - the memory is just sitting in a pool, waiting for the next time you allocate one.

Yes -- the same two blocks remain but no more. But it still annoys me -- I want no leaks reported at all. Is there anyway to clean the pool STL keeps track of? Or is there any way to have the CRT debug reporter not report these?

Background: I wanted to do things more cleanly, as before I converted an integer to a string using itoa() or sprintf(). I thought: let's use STL fully this time around.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!