1
Window / SFML 2.4.0, Ubuntu 16.04.2: memory leaks from GlxContext
« on: August 15, 2016, 03:29:08 am »
Hi,
I've run into what looks like memory leaks in SFML 2.4.0's GlxContext. The last part of this post is a patch that seems to address these leaks.
Compiler information:
The following program linked against SFML 2.4.0 and compiled with -fsanitize=address emits LeakSanitizer memory leak warnings on exit. No memory leak warnings are emitted under SFML 2.3.2.
The LeakSanitizer output looks like this:
The full compile/run session can be found at https://gitlab.peach-bun.com/snippets/27.
It looks like there are some missing XFree calls in GlxContext.cpp. (The LeakSanitizer output unfortunately runs into la-la memory space, but valgrind gives us a better picture.) The below diff applied to SFML commit 8df84935152b89a0f569058bb66e9e1bdc095bfa seems to fix the issue:
As far as I can tell, glXGetVisualFromFBConfig's return value is caller-owned. The inserted XFree calls are intended to take care of that.
I've run into what looks like memory leaks in SFML 2.4.0's GlxContext. The last part of this post is a patch that seems to address these leaks.
Compiler information:
$ g++ --version
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.2) 5.4.0 20160609
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.2) 5.4.0 20160609
The following program linked against SFML 2.4.0 and compiled with -fsanitize=address emits LeakSanitizer memory leak warnings on exit. No memory leak warnings are emitted under SFML 2.3.2.
#include <SFML/Window.hpp>
int main()
{
sf::Window window(sf::VideoMode(640, 480), "Test window");
window.setVisible(true);
bool running = true;
while (running) {
sf::Event event;
while (window.pollEvent(event)) {
switch (event.type) {
case sf::Event::Closed:
running = false;
break;
default:
break;
}
}
window.display();
}
window.close();
return 0;
}
int main()
{
sf::Window window(sf::VideoMode(640, 480), "Test window");
window.setVisible(true);
bool running = true;
while (running) {
sf::Event event;
while (window.pollEvent(event)) {
switch (event.type) {
case sf::Event::Closed:
running = false;
break;
default:
break;
}
}
window.display();
}
window.close();
return 0;
}
The LeakSanitizer output looks like this:
$ ./a.out
=================================================================
==10307==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 1280 byte(s) in 2 object(s) allocated from:
#0 0x7f5089977602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)
#1 0x7f5087ed9174 in XGetVisualInfo (/usr/lib/x86_64-linux-gnu/libX11.so.6+0x3b174)
#2 0x8e (<unknown module>)
Direct leak of 640 byte(s) in 1 object(s) allocated from:
#0 0x7f5089977602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)
#1 0x7f5087ed9174 in XGetVisualInfo (/usr/lib/x86_64-linux-gnu/libX11.so.6+0x3b174)
#2 0x1f (<unknown module>)
#3 0x5e85223a446818ff (<unknown module>)
Direct leak of 640 byte(s) in 1 object(s) allocated from:
#0 0x7f5089977602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)
#1 0x7f5087ed9174 in XGetVisualInfo (/usr/lib/x86_64-linux-gnu/libX11.so.6+0x3b174)
#2 0x1f (<unknown module>)
(...similar warnings elided...)
=================================================================
==10307==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 1280 byte(s) in 2 object(s) allocated from:
#0 0x7f5089977602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)
#1 0x7f5087ed9174 in XGetVisualInfo (/usr/lib/x86_64-linux-gnu/libX11.so.6+0x3b174)
#2 0x8e (<unknown module>)
Direct leak of 640 byte(s) in 1 object(s) allocated from:
#0 0x7f5089977602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)
#1 0x7f5087ed9174 in XGetVisualInfo (/usr/lib/x86_64-linux-gnu/libX11.so.6+0x3b174)
#2 0x1f (<unknown module>)
#3 0x5e85223a446818ff (<unknown module>)
Direct leak of 640 byte(s) in 1 object(s) allocated from:
#0 0x7f5089977602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)
#1 0x7f5087ed9174 in XGetVisualInfo (/usr/lib/x86_64-linux-gnu/libX11.so.6+0x3b174)
#2 0x1f (<unknown module>)
(...similar warnings elided...)
The full compile/run session can be found at https://gitlab.peach-bun.com/snippets/27.
It looks like there are some missing XFree calls in GlxContext.cpp. (The LeakSanitizer output unfortunately runs into la-la memory space, but valgrind gives us a better picture.) The below diff applied to SFML commit 8df84935152b89a0f569058bb66e9e1bdc095bfa seems to fix the issue:
diff --git a/src/SFML/Window/Unix/GlxContext.cpp b/src/SFML/Window/Unix/GlxContext.cpp
index 7251db2..4d4d831 100644
--- a/src/SFML/Window/Unix/GlxContext.cpp
+++ b/src/SFML/Window/Unix/GlxContext.cpp
@@ -482,8 +482,11 @@ void GlxContext::createSurface(GlxContext* shared, unsigned int width, unsigned
if (visual->visualid == visualInfo.visualid)
{
config = &configs[i];
+ XFree(visual);
break;
}
+
+ XFree(visual);
}
if (config)
@@ -640,8 +643,11 @@ void GlxContext::createContext(GlxContext* shared)
if (visual->visualid == visualInfo->visualid)
{
config = &configs[i];
+ XFree(visual);
break;
}
+
+ XFree(visual);
}
if (!config)
index 7251db2..4d4d831 100644
--- a/src/SFML/Window/Unix/GlxContext.cpp
+++ b/src/SFML/Window/Unix/GlxContext.cpp
@@ -482,8 +482,11 @@ void GlxContext::createSurface(GlxContext* shared, unsigned int width, unsigned
if (visual->visualid == visualInfo.visualid)
{
config = &configs[i];
+ XFree(visual);
break;
}
+
+ XFree(visual);
}
if (config)
@@ -640,8 +643,11 @@ void GlxContext::createContext(GlxContext* shared)
if (visual->visualid == visualInfo->visualid)
{
config = &configs[i];
+ XFree(visual);
break;
}
+
+ XFree(visual);
}
if (!config)
As far as I can tell, glXGetVisualFromFBConfig's return value is caller-owned. The inserted XFree calls are intended to take care of that.