PDA

View Full Version : GUI frameworks for C++



cyberslayer
February 27th, 2007, 04:06 AM
I am looking for a good cross platform OO GUI framework for C++. I have tried wxWidgets 2.8 but the Linux implementation uses leaky libraries that cause memory leaks at runtime (just valgrind the wxWidgets hello world program and you will see what I mean). I have also valgrinded the QT sample application in KDevelop and it has leaks too. Aren't there any good OO GUI frameworks for C++ that don't leak memory all over the place?

Thanks

WW
February 27th, 2007, 09:47 AM
You could try GTK+ (http://www.gtk.org), or FLTK (http://www.fltk.org). The C++ wrapper for GTK+ is gtkmm (http://www.gtkmm.org).

cyberslayer
February 27th, 2007, 07:21 PM
The problem is, GTK and the libraries it uses (glib, libX, pango, etc.) were one of the things that was causing wxWidgets to leak when I tested it. I have also tested GTK by itself with valgrind and it is just as leaky as wxWidgets and QT.

You would think that there would be a GUI framework that wouldn't leak memory all over the place but I guess not. I am amazed the this has not been fixed in major GUI frameworks like these!

Thanks for the reply

lnostdal
February 27th, 2007, 07:30 PM
riiight .. i am 100% certain that the leak is caused by an error you are doing or something you are misinterpreting

paste the "hello world" program that causes a leak when using GTK+

cyberslayer
February 27th, 2007, 07:43 PM
I doubt it. I am using the hello world app from KDevelop 3.3.4 and I did not modify the code or anything else so I doubt I am doing something wrong. However, I did post the code generated by KDevelop at the end of this post (as well as the valgrind output). Maybe the GTK hello world app has flaws in it but the QT and wxWidgets hello world apps also leak memory (even more actually).

test2.cc
#include <gtkmm/main.h>

#include "main_window.hh"

int main(int argc, char **argv)
{

Gtk::Main m(&argc, &argv);

main_window main_window;
Gtk::Main::run(main_window);
return 0;
}

main_window_glade.cc
// DO NOT EDIT THIS FILE ! It was created using glade--
// for gtk 2.8.3 and gtkmm 2.8.0
//
// Please modify the corresponding derived classes in ./src/main_window.cc


#if defined __GNUC__ && __GNUC__ < 3
#error This program will crash if compiled with g++ 2.x
// see the dynamic_cast bug in the gtkmm FAQ
#endif //
#include "config.h"
#include <gtkmmconfig.h>
#if GTKMM_MAJOR_VERSION==2 && GTKMM_MINOR_VERSION>2
#include <sigc++/compatibility.h>
#define GMM_GTKMM_22_24(a,b) b
#else //gtkmm 2.2
#define GMM_GTKMM_22_24(a,b) a
#endif //
#include "main_window_glade.hh"
#include <gdk/gdkkeysyms.h>
#include <gtkmm/accelgroup.h>

main_window_glade::main_window_glade(
) : Gtk::Window(Gtk::WINDOW_TOPLEVEL)
{ main_window = this;
gmm_data = new GlademmData(get_accel_group());
main_window->set_title("test2 Project");
main_window->set_modal(false);
main_window->property_window_position().set_value(Gtk::WIN_POS_ CENTER);
main_window->set_resizable(true);
main_window->property_destroy_with_parent().set_value(false);
main_window->show();
main_window->signal_delete_event().connect(SigC::slot(*this, &main_window_glade::quit), false);
}

main_window_glade::~main_window_glade()
{ delete gmm_data;
}

main_window.cc
// newer (non customized) versions of this file go to main_window.cc_new

// This file is for your program, I won't touch it again!

#include "config.h"
#include "main_window.hh"

bool main_window::quit(GdkEventAny *ev)
{ return 0;
}

valgrind output:
==27286== ERROR SUMMARY: 22 errors from 18 contexts (suppressed: 34 from 1)
==27286== malloc/free: in use at exit: 470,756 bytes in 5,082 blocks.
==27286== malloc/free: 11,088 allocs, 6,006 frees, 1,307,450 bytes allocated.
==27286== For counts of detected errors, rerun with: -v
==27286== searching for pointers to 5,082 not-freed blocks.
==27286== checked 1,597,376 bytes.
==27286==
==27286==
==27286== 292 (52 direct, 240 indirect) bytes in 1 blocks are definitely lost in loss record 50 of 120
==27286== at 0x4A2080E: malloc (vg_replace_malloc.c:149)
==27286== by 0x78135B0: (within /lib/libc-2.4.so)
==27286== by 0x7813CFE: __nss_database_lookup (in /lib/libc-2.4.so)
==27286== by 0x867A5CF: ???
==27286== by 0x867BA46: ???
==27286== by 0x77C9B14: getpwnam_r (in /lib/libc-2.4.so)
==27286== by 0x715C46F: (within /usr/lib/libglib-2.0.so.0.1200.4)
==27286== by 0x715D7BF: g_get_home_dir (in /usr/lib/libglib-2.0.so.0.1200.4)
==27286== by 0x54449FB: (within /usr/lib/libgtk-x11-2.0.so.0.1000.6)
==27286== by 0x544773C: _gtk_rc_init (in /usr/lib/libgtk-x11-2.0.so.0.1000.6)
==27286== by 0x5400D69: (within /usr/lib/libgtk-x11-2.0.so.0.1000.6)
==27286== by 0x7143020: g_option_context_parse (in /usr/lib/libglib-2.0.so.0.1200.4)
==27286==
==27286==
==27286== 1,600 bytes in 20 blocks are possibly lost in loss record 97 of 120
==27286== at 0x4A1FB37: calloc (vg_replace_malloc.c:279)
==27286== by 0x713DAE1: g_malloc0 (in /usr/lib/libglib-2.0.so.0.1200.4)
==27286== by 0x6DE4C7E: (within /usr/lib/libgobject-2.0.so.0.1200.4)
==27286== by 0x6DE4DCE: (within /usr/lib/libgobject-2.0.so.0.1200.4)
==27286== by 0x6DE53BC: g_type_init_with_debug_flags (in /usr/lib/libgobject-2.0.so.0.1200.4)
==27286== by 0x5C0B08E: gdk_pre_parse_libgtk_only (in /usr/lib/libgdk-x11-2.0.so.0.1000.6)
==27286== by 0x5400E12: (within /usr/lib/libgtk-x11-2.0.so.0.1000.6)
==27286== by 0x7142E96: g_option_context_parse (in /usr/lib/libglib-2.0.so.0.1200.4)
==27286== by 0x5400A4E: gtk_parse_args (in /usr/lib/libgtk-x11-2.0.so.0.1000.6)
==27286== by 0x5400AA8: gtk_init_check (in /usr/lib/libgtk-x11-2.0.so.0.1000.6)
==27286== by 0x5400AD8: gtk_init (in /usr/lib/libgtk-x11-2.0.so.0.1000.6)
==27286== by 0x4DB5B7F: Gtk::Main::init(int*, char***, bool) (in /usr/lib/libgtkmm-2.4.so.1.0.30)
==27286==
==27286==
==27286== 37,648 bytes in 15 blocks are possibly lost in loss record 117 of 120
==27286== at 0x4A1FA22: memalign (vg_replace_malloc.c:332)
==27286== by 0x4A1FA7B: posix_memalign (vg_replace_malloc.c:386)
==27286== by 0x714BC40: (within /usr/lib/libglib-2.0.so.0.1200.4)
==27286== by 0x714CF5B: g_slice_alloc (in /usr/lib/libglib-2.0.so.0.1200.4)
==27286== by 0x714D075: g_slice_alloc0 (in /usr/lib/libglib-2.0.so.0.1200.4)
==27286== by 0x6DEC44E: g_type_create_instance (in /usr/lib/libgobject-2.0.so.0.1200.4)
==27286== by 0x6DD528E: g_param_spec_internal (in /usr/lib/libgobject-2.0.so.0.1200.4)
==27286== by 0x6DD6EF9: g_param_spec_double (in /usr/lib/libgobject-2.0.so.0.1200.4)
==27286== by 0x5C2117F: (within /usr/lib/libgdk-x11-2.0.so.0.1000.6)
==27286== by 0x6DEBD1B: g_type_class_ref (in /usr/lib/libgobject-2.0.so.0.1200.4)
==27286== by 0x6DEC0EA: g_type_class_ref (in /usr/lib/libgobject-2.0.so.0.1200.4)
==27286== by 0x6DD2769: g_object_newv (in /usr/lib/libgobject-2.0.so.0.1200.4)
==27286==
==27286== LEAK SUMMARY:
==27286== definitely lost: 52 bytes in 1 blocks.
==27286== indirectly lost: 240 bytes in 10 blocks.
==27286== possibly lost: 39,248 bytes in 35 blocks.
==27286== still reachable: 431,216 bytes in 5,036 blocks.
==27286== suppressed: 0 bytes in 0 blocks.
==27286== Reachable blocks (those to which a pointer was found) are not shown.
==27286== To see them, rerun with: --show-reachable=yes

lnostdal
February 27th, 2007, 08:23 PM
ok, listen .. your code does not leak memory .. gtk allocates something it never frees - but it does not accumulate (leak) because it is a one-shot operation .. everything is freed by the OS when the process terminates

GLib/GObject also has a GC-system which makes life harder for valgrind .. to try to make it a bit easyer you can add some environment variables:
G_DEBUG=gc-friendly
G_SLICE=always-malloc

..but the one-shot allocations will still be there

edit:
here: http://live.gnome.org/Valgrind

cyberslayer
February 28th, 2007, 12:18 AM
gtk allocates something it never frees

That's what a memory leak is. There are also other leaks (for example add an about dialog and you will get more leaks although I haven't found any in GTK that accumulate). wxWidgets however, does have leaks that accumulate.


everything is freed by the OS when the process terminates

I know that but gtk should not be allocating things it does not free.

Anyway, it appears that all the good GUI frameworks I know about have leaks so I guess there aren't any that don't leak unless you know of any others.

lnostdal
February 28th, 2007, 01:32 AM
i use GTK+ software that runs for months(!) under moderate to very intensive use; it doesn't leak

running a "hello world" using GTK+ through valgrind i see that these are one-shot global initialization things: "init", "prepare", "loadfont", "parseargs" (argv-stuff): http://nostdal.org/~lars/programming/c/gtk-helloworld.c

use valgrinds suppression features and/or redefine your definition of leak so you can start focusing on what matters; coding and the real "accumulating leaks" - if you will

WW
February 28th, 2007, 04:05 AM
Have you tried FLTK?

cyberslayer
February 28th, 2007, 05:19 AM
I just tried out the hello world sample for FLTK. I valgrinded it and didn't detect any leaks. Hopefully, more complex apps won't leak either. Thanks for telling me about this.

runningwithscissors
February 28th, 2007, 09:19 AM
The "leaks" that you are seeing are resources that are supposed to last the duration of the process, hence, they're never explicitly freed.

It isn't something that will fill up your memory with prolonged use.

It is not exactly a very clean practice, but it isn't detrimental either. GTK apps do not leak memory.

cyberslayer
February 28th, 2007, 06:58 PM
The "leaks" that you are seeing are resources that are supposed to last the duration of the process, hence, they're never explicitly freed.

It isn't something that will fill up your memory with prolonged use.

It is not exactly a very clean practice, but it isn't detrimental either. GTK apps do not leak memory.

Yes, I know that the GTK leaks do not accumulate. However, it does make it harder to find other leaks in the apps with valgrind because you have to look through all the one time GTK leaks. This would be easier if GTK did not have these leaks because then the only leaks that showed up would be due to errors in the app. Anyway, there is no reason that GTK shouldn't free these one time allocations before the app exits. Allocating memory and not freeing it is bad (whether its a one time allocation or not).

j_g
March 1st, 2007, 04:42 AM
I qualify something (a resource, or memory allocation) as a "leak" if:

1) It is used once by the process and then never used again, but also never freed until the program ends. Typically, this happens when code doesn't properly track its resources, and therefore tends to just "lose" the resource until the OS finally frees it when the process ends.

2) The resource is still allocated even when the process ends.

Obviously, #2 is more serious than #1, but #1 is still annoying and can detrimentally impact system performance.

I don't consider it a "leak" if some routine allocates a resource that is used repeatedly during execution of the process. I have no doubt that GTK allocates some per-thread or per-process memory and resources that are used repeatedly by other GTK routines. After all, there is undoubtably some "state data" that needs to be maintained across calls (for example, lists of displays, screens, windows, etc). There is nothing "wrong" with this design, and in fact, the software could not do what it does without this behavior (ie, allocating resources that exist for the lifetime of the process).