Memleak in canvas_paint, update (was: Re: Memory errors in pango, thoughts on making it optional?)
Al Hooton <[email protected]> Sat, 04 Dec 2004 08:33:50 -0800
| Newsgroups | gmane.comp.scigraphica.gtkextra |
|---|---|
| Message-ID | <[email protected]> |
Hi Adrian,
On Fri, 2004-12-03 at 15:01 -0600, Adrian E. Feiguin wrote:
> Regarding the mem leaks, ..... You think you can pinpoint it more
> accurately?
I've been able to track it down to gtk_plot_canvas_paint(). I will keep
working to get lower in the stack, but for now I have a very small test
program that clearly demonstrates the leak (a gutted-out version of your
testgtkplotcanvas.c). I've attached it to this note, and I'll paste it
in-line below.
This example doesn't do much:
- Build a simple canvas with only one plot on it for a child
- Calls g_timeout_add to have the main loop call a handler every second
- The handler only calls gtk_plot_canvas_paint.
So, the only thing happening is that once every second a call to
gtk_plot_canvas_paint is made. There aren't any changes to the plot at
any point after it's created.
In a tool like memprof or valgrind, it's easy to see the memory used by
this process growing ever-larger (although some of the lower-level pango
problems cause these tools to bail out for other reasons, so it has
proven difficult to get enough information out of them to pinpoint this
further). However, if you just run "top" and watch the
testgtkplotcanvas process, you can see it growing.
I do understand that gtk/gdk/glib is a garbage-collected system, and
that you can't always tell exactly what's going on from watching "top",
or using a dynamic memory analyzer. However, this process will just
keep growing and growing, even though there's plenty of idle time. I
left it running last night, and it eventually consumed all 1.2GB of
virtual memory on my box (in about 6 hours).
I'll keep diving down in the next couple of days, because this one is a
total show-stopper for me at the moment. If you have any ideas,
thoughts or suggestions as to where I should concentrate my efforts,
please let me know.
Thanks,
Al
------------------------------
#include <math.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include <time.h>
#include <signal.h>
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include "gtkplot.h"
#include "gtkplotdata.h"
#include "gtkplotcanvas.h"
#include "gtkplotcanvasplot.h"
GtkWidget *canvas;
GtkPlotCanvasChild *child = NULL;
void
quit ()
{
gtk_main_quit();
}
void
sigStatus(int signum, siginfo_t *siginfo, void *notused)
{
gtk_plot_canvas_paint(GTK_PLOT_CANVAS(canvas));
}
int main(int argc, char *argv[]){
GtkWidget *window1;
GtkWidget *vbox1;
GtkWidget *scrollw1;
GtkWidget *active_plot;
gint page_width, page_height;
gfloat scale = 1.;
page_width = GTK_PLOT_LETTER_W * scale;
page_height = GTK_PLOT_LETTER_H * scale;
gtk_init(&argc,&argv);
window1=gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window1), "GtkPlotCanvas Demo");
gtk_widget_set_usize(window1,550,650);
gtk_container_border_width(GTK_CONTAINER(window1),0);
gtk_signal_connect (GTK_OBJECT (window1), "destroy",
GTK_SIGNAL_FUNC (quit), NULL);
vbox1=gtk_vbox_new(FALSE,0);
gtk_container_add(GTK_CONTAINER(window1),vbox1);
gtk_widget_show(vbox1);
scrollw1=gtk_scrolled_window_new(NULL, NULL);
gtk_container_border_width(GTK_CONTAINER(scrollw1),0);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollw1),
GTK_POLICY_ALWAYS,GTK_POLICY_ALWAYS);
gtk_box_pack_start(GTK_BOX(vbox1),scrollw1, TRUE, TRUE,0);
gtk_widget_show(scrollw1);
canvas = gtk_plot_canvas_new(page_width, page_height, 1.);
gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrollw1),
canvas);
gtk_widget_show(canvas);
active_plot = gtk_plot_new(NULL);
gtk_widget_show(active_plot);
child = gtk_plot_canvas_plot_new(GTK_PLOT(active_plot));
gtk_plot_canvas_put_child(GTK_PLOT_CANVAS(canvas),
child, .1, .1, .8, .65);
/* Set up the g_timeout */
g_timeout_add((guint) 1000, (GSourceFunc)&sigStatus, (gpointer)NULL);
gtk_widget_show(window1);
gtk_main();
return(0);
}
testgtkplotcanvas.c
(text/x-csrc, 2 KB)
#include <math.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include <time.h>
#include <signal.h>
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include "gtkplot.h"
#include "gtkplotdata.h"
#include "gtkplotcanvas.h"
#include "gtkplotcanvasplot.h"
GtkWidget *canvas;
GtkPlotCanvasChild *child = NULL;
void
quit ()
{
gtk_main_quit();
}
void
sigStatus(int signum, siginfo_t *siginfo, void *notused)
{
gtk_plot_canvas_paint(GTK_PLOT_CANVAS(canvas));
}
int main(int argc, char *argv[]){
GtkWidget *window1;
GtkWidget *vbox1;
GtkWidget *scrollw1;
GtkWidget *active_plot;
gint page_width, page_height;
gfloat scale = 1.;
page_width = GTK_PLOT_LETTER_W * scale;
page_height = GTK_PLOT_LETTER_H * scale;
gtk_init(&argc,&argv);
window1=gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window1), "GtkPlotCanvas Demo");
gtk_widget_set_usize(window1,550,650);
gtk_container_border_width(GTK_CONTAINER(window1),0);
gtk_signal_connect (GTK_OBJECT (window1), "destroy",
GTK_SIGNAL_FUNC (quit), NULL);
vbox1=gtk_vbox_new(FALSE,0);
gtk_container_add(GTK_CONTAINER(window1),vbox1);
gtk_widget_show(vbox1);
scrollw1=gtk_scrolled_window_new(NULL, NULL);
gtk_container_border_width(GTK_CONTAINER(scrollw1),0);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollw1),
GTK_POLICY_ALWAYS,GTK_POLICY_ALWAYS);
gtk_box_pack_start(GTK_BOX(vbox1),scrollw1, TRUE, TRUE,0);
gtk_widget_show(scrollw1);
canvas = gtk_plot_canvas_new(page_width, page_height, 1.);
gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrollw1), canvas);
gtk_widget_show(canvas);
active_plot = gtk_plot_new(NULL);
gtk_widget_show(active_plot);
child = gtk_plot_canvas_plot_new(GTK_PLOT(active_plot));
gtk_plot_canvas_put_child(GTK_PLOT_CANVAS(canvas), child, .1, .1, .8, .65);
/* Set up the g_timeout */
g_timeout_add((guint) 1000, (GSourceFunc)&sigStatus, (gpointer)NULL);
gtk_widget_show(window1);
gtk_main();
return(0);
}