Jump to content

  • Log In with Google      Sign In   
  • Create Account

Massive memory leak


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
14 replies to this topic

#1 CJ_COIMBRA   Crossbones+   -  Reputation: 838

Like
0Likes
Like

Posted 16 May 2013 - 04:54 AM

I am working on a project for a long time now and wasn't paying much attention to memory issues since they didn't cause any problems so far but I believe they will at some point. There are some actions to be taken like providing smaller assets to players that don't use/have full HD compatible displays and optimize some assets, yet I would like to know how do you guys (or girls why not!) deal with memory leaks. Is there something particularly important that I should look for when tracking the leaks? Are the leaks necessarily linked to "new" usage or should I look somewhere else too? Should a massive memory leak always be obvious to detect?

 

Also there is a second point, more specific for SFML users: I am using a resource manager class that loads all assets and provide them the other classes as needed or at the game boot. The resource manager holds sf::Image's and the classes that need to drawn something holds sf::Sprite's. Now, if I have two,three,four...a thousand similar instances of this class, will the resource manager still take just the memory needed for one sf::Image used by the consumer class or each instance will take more and more memory? Does this make sense at all?

 

Thanks in advance.



Sponsor:

#2 Álvaro   Crossbones+   -  Reputation: 13935

Like
6Likes
Like

Posted 16 May 2013 - 05:06 AM

My first tool against memory leaks is discipline:

 (1) Use standard containers (of objects, not pointers) instead of rolling your own data structures.

 (2) Use a smart pointer (probably std::unique_ptr) when you need polymorphism.

 (3) Be very clear about which object owns which resource, and release the resource in the object's destructor.

 

Now that you already have a mess because you probably haven't followed the principles above, you can try to use tools like valgrind to help you find problems with how you are using memory. It is a pretty safe bet that `new' is involved.

 

Massive memory leaks should be easier to detect than small ones. There is also more of an incentive to fix them. :)

 

I am not very familiar with SFML, so I won't comment on the second part of your post.



#3 Felix Ungman   Members   -  Reputation: 1067

Like
2Likes
Like

Posted 16 May 2013 - 05:28 AM

There's only one way to deal with leaks: Find them and fix them.

 

Leaks don't necessarily come from new/malloc statements in your own code, they could also happen indirectly if you don't call the proper cleanup methods in library code.

 

There are two methods to find leaks:

- Use a static analyzer that examines logical errors in your code.

- Run the executable using a memory profiler and watch for unreleased resources.

 

With good tools tiny leaks should be as easy to detect as massive ones.


Edited by Felix Ungman, 16 May 2013 - 05:29 AM.

openwar  - the real-time tactical war-game platform


#4 VladR   Members   -  Reputation: 722

Like
1Likes
Like

Posted 16 May 2013 - 07:42 AM

Should a massive memory leak always be obvious to detect?

Absolutely. I take it you check the memory footprint in Task manager. There's no way you could miss a massive leak this way.

 

Then again, your definition of massive leak may differ from mine...

 

 

Are the leaks necessarily linked to "new" usage or should I look somewhere else too?

In gamedev there are two major types of leaks - Memory Leaks and Resource leaks, which are caused by unreleased graphics resources (e.g. textures, RTs, VB / IB, ...). Those are best checked by DirectX debug runtime (change the setting in Control Panel and enjoy hundreds of colorful messages in Output pane of Visual Studio).

 

 

Also, if you are not using Smart Pointers and are still trying to match new/delete, there's nothing better than the experience of rolling out your own _NEW, _DELETE and going through the logs and matching it all.

 

Usually, that exercise alone is enough to persuade one it's really time to move to Smart Pointers smile.png


VladR    My 3rd person action RPG on GreenLight:    http://steamcommunity.com/sharedfiles/filedetails/?id=92951596

 


#5 KnolanCross   Members   -  Reputation: 1369

Like
1Likes
Like

Posted 16 May 2013 - 07:52 AM

Do you use linux (or may it)? If you do look for a program called valgrind.

 

It will give you a memory report that is very accurate and includes memory leaks and memory errors. I always validate my code with it.

 

The link for the project is here: http://valgrind.org/


Currently working on a scene editor for ORX (http://orx-project.org), using kivy (http://kivy.org).


#6 Satharis   Members   -  Reputation: 1298

Like
1Likes
Like

Posted 16 May 2013 - 10:48 AM

Also there is a second point, more specific for SFML users: I am using a resource manager class that loads all assets and provide them the other classes as needed or at the game boot. The resource manager holds sf::Image's and the classes that need to drawn something holds sf::Sprite's. Now, if I have two,three,four...a thousand similar instances of this class, will the resource manager still take just the memory needed for one sf::Image used by the consumer class or each instance will take more and more memory? Does this make sense at all?

Each sf::Image(or sf::Texture primarily in 2.0) is a unique instance. If you make 100 sf::Textures and tell them all to load the same file you'll have 100 copies of the image data. What you -should- do is keep one copy of the image in your resource manager and just return references to any caller asking for the object. You could do that by using an unordered_map or something using the key as the filepath of the object, or some kind of identifier like an assetname you invention up.

Each object can easily have it's own sf::Sprite, it's supposed to be a lightweight class from what I can tell. Then you can just set it to whatever image/texture you want to immediately use.

#7 Plethora   Members   -  Reputation: 679

Like
1Likes
Like

Posted 16 May 2013 - 05:05 PM

Also there is a second point, more specific for SFML users: I am using a resource manager class that loads all assets and provide them the other classes as needed or at the game boot. The resource manager holds sf::Image's and the classes that need to drawn something holds sf::Sprite's. Now, if I have two,three,four...a thousand similar instances of this class, will the resource manager still take just the memory needed for one sf::Image used by the consumer class or each instance will take more and more memory? Does this make sense at all?

 

I'm not sure if this helps, but personally I have a small class based mostly around an std::map that holds my sf::texture objects (sf::image in your case).  That's the only place that textures get loaded and they are all loaded one time at startup.  The class has a getSpriteByKey method that returns an sf::sprite with a given texture/image attached to it.  I don't create sprites until I need them (though I do try to keep them around once I have created them if I know I'll need them again where possible).


I'm working on a game!  It's called "Spellbook Tactics".  I'd love it if you checked it out, offered some feedback, etc.  I am very excited about my progress thus far and confident about future progress as well!

 

http://infinityelephant.wordpress.com


#8 CJ_COIMBRA   Crossbones+   -  Reputation: 838

Like
0Likes
Like

Posted 16 May 2013 - 07:50 PM

Thanks for the suggestions. They´ve helped me. I think I found the problem (or the worst part of it). I have a std::vector with dynamic allocated objects being pushed under a certain condition. The problem is that when another certain condition is met, I was just popping them. So I guess I should´ve used delete before popping them? Is this correct? I think this is the problem because after commenting this relevant part of the code my memory consumption has stopped to increase.



#9 CJ_COIMBRA   Crossbones+   -  Reputation: 838

Like
0Likes
Like

Posted 16 May 2013 - 08:22 PM

Yep, that solved the problem. There are other minor leaks to fix so I´ll assume the same solution for now.

 

edit: just a note, I wasn´t popping the objects. I was doing "erase" from std::vector. I am still doing it but now I delete them before that. I read somewhere that I should nullify AND also delete. Is this correct?


Edited by CJ_COIMBRA, 16 May 2013 - 08:24 PM.


#10 Satharis   Members   -  Reputation: 1298

Like
2Likes
Like

Posted 16 May 2013 - 09:14 PM

Yep, that solved the problem. There are other minor leaks to fix so I´ll assume the same solution for now.

 

edit: just a note, I wasn´t popping the objects. I was doing "erase" from std::vector. I am still doing it but now I delete them before that. I read somewhere that I should nullify AND also delete. Is this correct?

Erase or pop_back do the same thing essentially, destroy the object. In the case of destroying pointers you literally just destroy that one pointer to the object and the object remains floating in memory, oblivious to the fact that no other pointers or references may have access to it. Obviously a memory leak.

 

Usually you set a pointer to NULL(which is 0) so that if you later check the pointer against null, you will know if it is currently pointing to a hopefully live object, or if it was set to point to nothing, perhaps to wait for you to assign it to something else.

 

On the flipside, delete frees the actual memory the pointer is pointing to, leaving the pointer still alive but pointing to a now dead object.

 

You probably know most of this, but I was just re-iterating as a start point. You only should set a pointer to null if it is going to be alive still. pop_back or delete, frees the actual pointer, so it won't exist any longer in the container, thus you don't really need to set it to null.

 

In other words: delete any allocated objects you are done using, set the pointer to null if it isn't going to be destroyed anyway. Though you might want to set it to null as a sanity check if you do something like.. declare it at the top of a function and someone might be tempted to use it at the bottom. That obviously isn't the case with regards to container classes since you won't be inside them. You definitely want to set things like member pointers to NULL.



#11 Squared'D   Members   -  Reputation: 2259

Like
1Likes
Like

Posted 16 May 2013 - 10:54 PM

edit: just a note, I wasn´t popping the objects. I was doing "erase" from std::vector. I am still doing it but now I delete them before that. I read somewhere that I should nullify AND also delete. Is this correct?


You must call delete otherwise the object will still exist, but you don't need to set the pointer to NULL if you call erase or delete the entire vector as the pointer will be "destroyed" anyway. Actually setting it to NULL will be a wasted instruction.

Learn all about my current projects and watch some of the game development videos that I've made.

Squared Programming Home

New Personal Journal

 


#12 Squared'D   Members   -  Reputation: 2259

Like
0Likes
Like

Posted 16 May 2013 - 11:39 PM

sorry double post.


Edited by Squared'D, 16 May 2013 - 11:51 PM.

Learn all about my current projects and watch some of the game development videos that I've made.

Squared Programming Home

New Personal Journal

 


#13 Álvaro   Crossbones+   -  Reputation: 13935

Like
0Likes
Like

Posted 17 May 2013 - 05:17 AM

So you have a vector of pointers, in violation of my rule (1) above. Why not make it a vector or objects instead?



#14 CJ_COIMBRA   Crossbones+   -  Reputation: 838

Like
0Likes
Like

Posted 17 May 2013 - 05:40 AM

Yeah, I tried that but for some reason it wont work in my case (everything seems fine but then it crashes every time the execution reaches the point that the object is pushed into the vector), so I changed back to pointers. Perhaps it's related to the class I am trying to push into the vector. I'll look more into that later, I just started to optimize and fix things on my project and I've seen that's it's going to be a huge work.

 

By the way do you know what would be the ideal amount of memory I should recommend based on how much my application uses? I mean, we see lots of games asking for 2GB minimum and 4 GB recommended (in example) but obviously those applications don't take 2GB or 4GB to run because there are other things happening on the system. Is there a "formula" that gives you the amount you should recommend based on how much you will in fact use?

 

Thanks again!



#15 Álvaro   Crossbones+   -  Reputation: 13935

Like
0Likes
Like

Posted 17 May 2013 - 06:13 AM

Yeah, I tried that but for some reason it wont work in my case (everything seems fine but then it crashes every time the execution reaches the point that the object is pushed into the vector), so I changed back to pointers.

 

I would say go back to objects and fix the crash. You may have some other bug and the use of pointers is just masking it.






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS