Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Detecting Memory Leaks  (Read 3479 times)

0 Members and 1 Guest are viewing this topic.

Contadotempo

  • Full Member
  • ***
  • Posts: 167
  • Firelink Shrine
    • View Profile
Detecting Memory Leaks
« on: December 23, 2010, 08:00:59 pm »
Hi,
I wrote an sf::Image manager called "class imStorage" based on an resource manager on the wiki and used Visual Studio 2010's debug mode to detect memory leaks.
For some reason, it's detecting a whole bunch of leaks, however I'm having trouble identifying what could be wrong.

Every image is stored on an std::map:
Code: [Select]
std::map<std::string,sf::Image*> bStore

Here's is the code for getting an image:
Code: [Select]

sf::Image *imStorage::GetImage(std::string Link)
{
    //if the image is already in the map, then return the image from it
    if(SearchManager(Link))
    {
        return bStore[Link];
    }
    //else allocate it from a Link to the path
    else
    {
        sf::Image *bHolder = new sf::Image;

        if(bHolder->LoadFromFile(Link))
        {
            bStore.insert(std::pair<std::string,sf::Image*>(Link,bHolder));
            std::cout << "Gestor de Imagens $ Inserido: " << Link << std::endl;
            return bStore[Link];
        }
        else
        {
        delete bHolder;
        }
return NULL;
    }
return NULL;
}

bool imStorage::SearchManager(std::string Link)
{
    std::map<std::string,sf::Image*>::iterator it;
    it = bStore.find(Link);
    if(it != bStore.end())
    {
        return true;
    }
    else return false;
}





And finally here's the destructor:
Code: [Select]
imStorage::~imStorage()
{
while(bStore.begin()!=bStore.end())
{
delete bStore.begin()->second;
bStore.erase(bStore.begin());
}

}


I get the following messages after executing:
Quote
Detected memory leaks!
Dumping objects ->
{136} normal block at 0x00334C20, 8 bytes long.
 Data: < S      > 14 53 1F 00 00 00 00 00
{135} normal block at 0x00334BD0, 20 bytes long.
 Data: < K3  K3  K3     > D0 4B 33 00 D0 4B 33 00 D0 4B 33 00 CD CD CD CD
{134} normal block at 0x00334B88, 8 bytes long.
 Data: < I3     > D4 49 33 00 00 00 00 00
{133} normal block at 0x003349C8, 384 bytes long.
 Data: <$            K3 > 24 CE 1E 00 01 00 00 00 01 00 00 00 88 4B 33 00
{132} normal block at 0x00334988, 4 bytes long.
 Data: < I3 > C8 49 33 00
Object dump complete.


Problem is, I have no idea what these mean and I can't identify what's causing the leaks.
What could be wrong? Could it be a false positive? Should I use any other memory leak detection tool?

If you have any idea or suggestion please be sure to give me a heads up.
Thanks in advance  :)

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Detecting Memory Leaks
« Reply #1 on: December 23, 2010, 09:42:18 pm »
First of all, have you checked that the leak disappears if you remove your manager? If it's only a single leak, it may be caused by SFML (if you're using 1.6).

Then, here is the right (optimized and simplified) way to write exactly the same code ;)
Code: [Select]
// use and abuse typedefs!
typedef std::map<std::string,sf::Image*> ImageMap;

sf::Image *imStorage::GetImage(const std::string& Link) // const reference to avoid copy
{
    // if the image is already in the map, then return the image from it

    // calling SearchManager + operator[] makes 2 searches, you only need one
    ImageMap::iterator it = bStore.find(Link);
    if (it != bStore.end())
    {
        return it->second;
    }
    //else allocate it from a Link to the path
    else
    {
        sf::Image* bHolder = new sf::Image;
        if (bHolder->LoadFromFile(Link))
        {
            // same here, you were making 2 searches
            std::pair<ImageMap::iterator, bool> result;
            result = bStore.insert(std::make_pair(Link, bHolder)); // std::make_pair allows shorter syntax

            std::cout << "Gestor de Imagens $ Inserido: " << Link << std::endl;
            return result.first;
        }
        else
        {
           delete bHolder;
           return NULL;
        }
    }
}

bool imStorage::SearchManager(const std::string& Link)
{
    // isn't it cute?
    return bStore.find(Link) != bStore.end();
}

imStorage::~imStorage()
{
   // no need to erase, the map will be destroyed anyway because this is the... destructor
   for (ImageMap::iterator it = bStore.begin(); it != bStore.end(); ++it)
      delete it->second;
}
Laurent Gomila - SFML developer

Contadotempo

  • Full Member
  • ***
  • Posts: 167
  • Firelink Shrine
    • View Profile
Detecting Memory Leaks
« Reply #2 on: December 24, 2010, 06:26:13 pm »
Yeah it appears to be coming from the manager. I tried recompiling SFML (1.6) again just to be sure but it appears they're still there even with the optimized code for the manager. It gives me the exact same leaks. Could be a false positive?

One more thing. I didn't understand very well what's happening in this part specially on the return part:
Quote from: "Laurent"
Code: [Select]
if (bHolder->LoadFromFile(Link))
{
      // same here, you were making 2 searches
      std::pair<ImageMap::iterator, bool> result;
      result = bStore.insert(std::make_pair(Link, bHolder)); //std::make_pair allows shorter syntax

      std::cout << "Gestor de Imagens $ Inserido: " << Link << std::endl;
      return result.first;
}


I made it "return bStore[Link];" (doing 2 searches sadly) again since it couldn't compile with "return result.first;".
error: cannot convert 'std::_Rb_tree_iterator<std::pair<const std::basic_string<char>, sf::Image*> >' to 'sf::Image*' in return

By the way, this made my day haha:
Quote from: "Laurent"
Code: [Select]

bool imStorage::SearchManager(const std::string& Link)
{
    // isn't it cute?
    return bStore.find(Link) != bStore.end();
}

I really need to learn how to use bool types more effectively.
Thanks and sorry for all the trouble  :)

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Detecting Memory Leaks
« Reply #3 on: December 24, 2010, 10:08:00 pm »
Quote
Yeah it appears to be coming from the manager. I tried recompiling SFML (1.6) again just to be sure but it appears they're still there even with the optimized code for the manager. It gives me the exact same leaks. Could be a false positive?

Yep, definitely weird. I don't see any leak there.
I think there's some way to get more detailed information about the leak, especially the file and line of allocation.

Quote
One more thing. I didn't understand very well what's happening in this part specially on the return part:

In fact, std::map::insert returns a pair<iterator, bool>. The iterator points to the inserted element, and the boolean says whether the key was already in the map or not.

Quote
error: cannot convert 'std::_Rb_tree_iterator<std::pair<const std::basic_string<char>, sf::Image*> >' to 'sf::Image*' in return

Woops, this is an iterator so it needs dereferencing:
Code: [Select]
return *result.first;
Laurent Gomila - SFML developer

Contadotempo

  • Full Member
  • ***
  • Posts: 167
  • Firelink Shrine
    • View Profile
Detecting Memory Leaks
« Reply #4 on: December 25, 2010, 02:41:20 pm »
Just tested the storage by inserting a lot of images and then destroyed them. The memory in use was back to the original + a slight overhead so I don't think there's any problem. Thanks Laurent  :wink:

May I ask one more question though? It's unrelated to the problem but this way I won't end up creating another topic.
When I move the Render Window by moving the titlebar with the mouse,

everything that's being drawn on the window stops moving, and after I let the window go everything moves again but becomes out of sync. Is there any way to fix this by not stopping what's being drawn when moving the window? It's probably related to GetFrameTime() function since I use it in every movement but if I remove it, what else could I use to get smooth movements?

Thanks for for all the help, great community!

Groogy

  • Hero Member
  • *****
  • Posts: 1469
    • MSN Messenger - groogy@groogy.se
    • View Profile
    • http://www.groogy.se
    • Email
Detecting Memory Leaks
« Reply #5 on: December 25, 2010, 02:50:17 pm »
You could probably check if the mouse is inside using the events Entered and it's counterpart which name eludes me at the moment. And when the first "Entered" event is encountered draw first one empty black screen and then continue. Easy fix, not pretty but should work.
Developer and Maker of rbSFML and Programmer at Paradox Development Studio

Drektar

  • Jr. Member
  • **
  • Posts: 77
    • View Profile
Detecting Memory Leaks
« Reply #6 on: December 25, 2010, 04:56:18 pm »
When you click on the titlebar with the mouse the OS don't let you draw anything on the window. So you program is in pause. When you stop moving the window, the program continue.
If your program was in pause for 3 second, GetFrameTime() will give you more than 3 second... That's normal.

If you don't want to use getFrameTime() you can use a fixed framerate

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Detecting Memory Leaks
« Reply #7 on: December 25, 2010, 06:48:01 pm »
Quote
It's unrelated to the problem but this way I won't end up creating another topic.

Well, it's better if problems are properly split/categorized/entitled rather than mixing unrelated things in the same discussion.
I don't know why so many people think it's a "waste" to create new topics ;)

The OS blocks the execution flow while you move the window, and there's nothing SFML can do. If you want to avoid huge gaps and messed up calculations, you can simply skip the update when elapsed time is greater than 1 second (for example).
Laurent Gomila - SFML developer

Contadotempo

  • Full Member
  • ***
  • Posts: 167
  • Firelink Shrine
    • View Profile
Detecting Memory Leaks
« Reply #8 on: December 26, 2010, 05:44:24 pm »
I'll be trying those solutions then. I'll probably stick with a fixed framerate.
Thank you all :)
Quote from: "Laurent"
I don't know why so many people think it's a "waste" to create new topics ;)

On some forums moderators are really strict and they demand that all questions should be in the same topic.
Since I'm fairly new here I still didn't know how far I could go on creating topics/post frequency but I'm happy to hear that.

Once again thanks for all the help, everything seems to be working fine  :)

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Detecting Memory Leaks
« Reply #9 on: December 26, 2010, 05:57:34 pm »
Quote
On some forums moderators are really strict and they demand that all questions should be in the same topic.

If these questions still relate to the initial problem. But if it's a new question, nobody will ever tell you to put it in the same topic.
Laurent Gomila - SFML developer