Welcome, Guest. Please login or register.

Author Topic: [SEMI-SOLVED] I Think I Found A Memory Leak  (Read 1986 times)

0 Members and 1 Guest are viewing this topic.

7krs

  • Newbie
  • *
  • Posts: 39
    • View Profile
    • Email
[SEMI-SOLVED] I Think I Found A Memory Leak
« on: January 16, 2013, 10:01:13 PM »
A minimal example:

    sf::RenderWindow* ptr = new sf::RenderWindow(sf::VideoMode(800, 600, 32), "title");
    ptr->setActive(false);
    while (true)
    {
        std::thread([=]()
                    {
                        ptr->setActive(true);
                        ptr->setActive(false);
                    }
                    ).join();
    }
 

Memory keeps rising (from ~12MB to over 300MB). Requesting confirmations.
« Last Edit: January 18, 2013, 07:46:00 PM by 7krs »

eXpl0it3r

  • Hero Member
  • *****
  • Posts: 4276
    • View Profile
    • development blog
    • Email
Re: I Think I Found A Memory Leak
« Reply #1 on: January 16, 2013, 10:11:57 PM »
Please provide the exact SFML version (i.e. from where you got it) and how you've been checking the 'memory leak'. Then you should provide a complete example (with main() and inclusions) that doesn't have a memory leak by definition (you never call delete).

It might well be that the memory you see allocated is just made available from the OS to the application, without the application actually using it. OS memory allocation isn't just a simple allocation/release on request, it's way more complex and there's mostly no way to actually predict when what happens. Thus a correct memory leak detection software is needed, although they might also show memory leaks where non are.

7krs

  • Newbie
  • *
  • Posts: 39
    • View Profile
    • Email
Re: I Think I Found A Memory Leak
« Reply #2 on: January 16, 2013, 10:24:18 PM »
...

My exact version appears to be "SFML-2.0-rc-102-g044eb85" and was downloaded from this website (the github link) on the 10th of November 2012. I check memory usage with the "System Monitor" provided by Linux Mint 13 x64.


#include <SFML/Graphics.hpp>
#include <thread>

int main()
{
    sf::RenderWindow* ptr = new sf::RenderWindow(sf::VideoMode(800, 600, 32), "title");
    ptr->setActive(false);
    while (true)
    {
        std::thread([=]()
                    {
                        ptr->setActive(true);
                        ptr->setActive(false);
                    }
                    ).join();
    }
    return 0;
}
 

7krs

  • Newbie
  • *
  • Posts: 39
    • View Profile
    • Email
Re: I Think I Found A Memory Leak
« Reply #3 on: January 17, 2013, 06:40:21 AM »
I just downloaded the latest repositories (LaurentGomila-SFML-9fac5d7). Built both Release and Debug mode using CMake. The error persists.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 27404
    • View Profile
    • SFML's website
    • Email
Re: I Think I Found A Memory Leak
« Reply #4 on: January 17, 2013, 06:45:15 AM »
It's not a leak. The memory will be freed when the window is destroyed. It rises because internally, because of some ugly magic, a new OpenGL context is created in each new thread. And since SFML is not notified when a thread dies, it can only release the associated context at the "end" (when no SFML resource exist anymore). Hopefully, in a real application you won't create drawing threads in a loop like that ;)

« Last Edit: January 17, 2013, 06:51:37 AM by Laurent »
Laurent Gomila - SFML developer

7krs

  • Newbie
  • *
  • Posts: 39
    • View Profile
    • Email
Re: I Think I Found A Memory Leak
« Reply #5 on: January 17, 2013, 07:39:17 AM »
What about the following code that causes a segmentation fault? Without the thread, it does not throw  a segfault. Why?

#include <SFML/Graphics.hpp>
#include <thread>

int main()
{
    sf::RenderWindow* ptr;
    while (true)
    {
        ptr = new sf::RenderWindow(sf::VideoMode(800, 600, 32), "title");
        ptr->setActive(false);
        std::thread([=]()
                    {
                        ptr->setActive(true);
                        ptr->setActive(false);
                    }
                    ).join();
        ptr->setActive(true);
        ptr->close();
        std::this_thread::sleep_for(std::chrono::seconds(1));
        delete ptr;
    }
    return 0;
}

 

#0 0x7ffff1749239   ??() (/usr/lib/fglrx/dri/fglrx_dri.so:??)
#1 0x7ffff17b040e   ??() (/usr/lib/fglrx/dri/fglrx_dri.so:??)
#2 0x7ffff18878c2   ??() (/usr/lib/fglrx/dri/fglrx_dri.so:??)
#3 0x7ffff17a0384   ??() (/usr/lib/fglrx/dri/fglrx_dri.so:??)
#4 0x7ffff2444295   ??() (/usr/lib/fglrx/dri/fglrx_dri.so:??)
#5 0x7ffff243fa73   ??() (/usr/lib/fglrx/dri/fglrx_dri.so:??)
#6 0x7ffff2440cb6   ??() (/usr/lib/fglrx/dri/fglrx_dri.so:??)
#7 0x7ffff244fa68   ??() (/usr/lib/fglrx/dri/fglrx_dri.so:??)
#8 0x7ffff244ff86   ??() (/usr/lib/fglrx/dri/fglrx_dri.so:??)
#9 0x7ffff3078e83   ??() (/usr/lib/fglrx/dri/fglrx_dri.so:??)
#10 0x7ffff2ee8dc9   ??() (/usr/lib/fglrx/dri/fglrx_dri.so:??)
#11 0x7ffff1743112   ??() (/usr/lib/fglrx/dri/fglrx_dri.so:??)
#12 (   0x00007fffffffd6c0 in ??() (??:??)
#13 0x7ffff30e0891   ??() (/usr/lib/fglrx/dri/fglrx_dri.so:??)
#14 (   0x0000000000000026 in ??() (??:??)
#15 0x7ffff7de992d   ??() (/lib64/ld-linux-x86-64.so.2:??)

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 27404
    • View Profile
    • SFML's website
    • Email
Re: I Think I Found A Memory Leak
« Reply #6 on: January 17, 2013, 07:41:07 AM »
Could you recompile in debug and try to get a more detailed call stack?
Laurent Gomila - SFML developer

7krs

  • Newbie
  • *
  • Posts: 39
    • View Profile
    • Email
Re: I Think I Found A Memory Leak
« Reply #7 on: January 17, 2013, 07:46:37 AM »
I did, identical call stack.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 27404
    • View Profile
    • SFML's website
    • Email
Re: I Think I Found A Memory Leak
« Reply #8 on: January 17, 2013, 07:58:46 AM »
Did you compile SFML in debug mode?
Laurent Gomila - SFML developer

7krs

  • Newbie
  • *
  • Posts: 39
    • View Profile
    • Email
Re: I Think I Found A Memory Leak
« Reply #9 on: January 17, 2013, 08:10:51 AM »
Most definitely, I even rebuilt them right now. I link to the -d.so files, which were created by the created project when entering Debug in CMake.

However, I think this may be an ATI / AMD driver problem:
https://bbs.archlinux.org/viewtopic.php?pid=401468

Edit:
Installing fglrx updates (using Synaptic)...
« Last Edit: January 17, 2013, 08:18:15 AM by 7krs »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 27404
    • View Profile
    • SFML's website
    • Email
Re: I Think I Found A Memory Leak
« Reply #10 on: January 17, 2013, 08:17:30 AM »
Quote
However, I think this may be an ATI / AMD driver problem:
https://bbs.archlinux.org/viewtopic.php?pid=401468
Have you tried the proposed fix?
Laurent Gomila - SFML developer

7krs

  • Newbie
  • *
  • Posts: 39
    • View Profile
    • Email
Re: I Think I Found A Memory Leak
« Reply #11 on: January 17, 2013, 08:37:57 AM »
I haven't tried it in the exact form because I do not have Arch Linux, but I downloaded the latest drivers and even restarted. It does not help my issue.

Edit: Seems to be a common problem when searching about fglrx on the internet (gamers, programmers mostly). Very annoying tho. I'll see if I can edit my design a bit so the drawing thread can just transfer control to a different location instead of being re-created.

Edit2: Is there no way to force some kind of cleanup? I'm gonna try to edit the some sfml sources...
« Last Edit: January 17, 2013, 10:51:29 AM by 7krs »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 27404
    • View Profile
    • SFML's website
    • Email
Re: I Think I Found A Memory Leak
« Reply #12 on: January 17, 2013, 02:48:06 PM »
Quote
Is there no way to force some kind of cleanup?
There is. Play with the private functions in GlContext.cpp and make public what you need.
Laurent Gomila - SFML developer

7krs

  • Newbie
  • *
  • Posts: 39
    • View Profile
    • Email
Re: I Think I Found A Memory Leak
« Reply #13 on: January 17, 2013, 04:10:55 PM »
There is. Play with the private functions in GlContext.cpp and make public what you need.

I looked at it and it's an abstract base class with only a one private function, and two protected functions.

protected :
    GlContext();
    static int evaluateFormat(unsigned int bitsPerPixel, const ContextSettings& settings, int colorBits, int depthBits, int stencilBits, int antialiasing);
    ContextSettings m_settings; ///< Creation settings of the context

private:
    void initialize();
 

On Linux we implement GlxContext, so I opened the GlxContext .hpp and .cpp. I'm focussing on the destructor, since I'm using this testing code:

#ifdef DEBUG
#include <iostream>
#endif

#include <SFML/Graphics.hpp>
#include <thread>

int main()
{
    // The drawer thread, active during the entire program's lifetime, constant drawing ////////////
    std::thread([&]()
                {
                    sf::RenderWindow wnd(sf::VideoMode(300, 200, 32), "Title");
                    wnd.setFramerateLimit(1);
                    while (true)
                    {
                        wnd.clear();
                        wnd.display();
                    }
                }
                ).detach();
    //////////////////////////////////////////////////////////////////////////////////////////////


    // Simulation of switching states ////////////////////////////////////////////////////////////
    while (true)
    {
        std::thread([&]()
                    {
                        sf::RenderTexture rt;
                        std::this_thread::sleep_for(std::chrono::seconds(1));
                    } // rt should be destroyed here, but its effect on the memory remains.
                    ).join();
    }
    //////////////////////////////////////////////////////////////////////////////////////////////

    return 0;
}
 

And whenever a window is active, the RenderTexture destructor is NOT properly called! Try to comment out the window thread, it'll not leak. With the window, it does leak! If we un-thread the state-switcher, it also does not leak. So I decided to take a closer look at the destructor:

GlxContext::~GlxContext()
{
    // Destroy the context
    if (m_context)
    {
        if (glXGetCurrentContext() == m_context)
            glXMakeCurrent(m_display, None, NULL);
        glXDestroyContext(m_display, m_context);
    }
   
    // Destroy the window if we own it
    if (m_window && m_ownsWindow)
    {
        XDestroyWindow(m_display, m_window);
        XFlush(m_display);
    }

    // Close the connection with the X server
    CloseDisplay(m_display);
}


Seems alright, we then have code from the base class's virtual destructor:

GlContext::~GlContext()
{
    // Deactivate the context before killing it, unless we're inside Cleanup()
    if (sharedContext)
        setActive(false);
}
 

An old foe? I showed that setActive causes memory expansion. Now even when the object is destroyed, memory is expanded. Does it have something to do with this? What about the functions in the GlxContext destructor? XFlush is ignored when the window is not owned? Am I even on the right tracks here?

Anyway, I removed the contents of ~GlContext(), however, I now get an error when rebuilding my testing scenario about an error in WindowStyle.hpp, line 40. Wat do?

binary1248

  • Hero Member
  • *****
  • Posts: 575
  • I am awesome.
    • View Profile
    • Google
Re: I Think I Found A Memory Leak
« Reply #14 on: January 17, 2013, 04:17:04 PM »
It's not a leak. The memory will be freed when the window is destroyed.
Actually if you ask me, the program doesn't leak, but within the program there is a leak because memory isn't being freed when a resource is not used anymore. It's like a server daemon leaking one byte every minute, but the daemon developer saying "our daemon doesn't leak, the allocator frees everything on exit". I wouldn't want to run that for too long ;).

It rises because internally, because of some ugly magic, a new OpenGL context is created in each new thread.
Yes the context management is really black magic :P. I already tried going through it many times but gave up after a few hours ^^.

And since SFML is not notified when a thread dies
What? Since when can you not be notified of a thread terminating? There are ways to do this...
SFGUI # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).