Memory Leak with pango_layout_new()



I've got a major memory leak in an applicaton and I tracked it down to the 
following: if I create a PangoLayout with pango_layout_new() and then use 
pango_layout_set_text(), I get a memory leak even when I try to free the 
memory with g_object_unref(). However, if I replace those function calls with 
a call to gtk_widget_create_pango_layout(), there is no memory leak. The 
memory leak is very obvious: on the real app, I'm losing almost 3 Megabytes 
per hour. "memprof" also very clearly shows the leak. I'm using Debian 
"sarge" and with the standard versions of the gtk development packages for 
that OS. I am pretty new with gtk programming. Am I doing something simple 
wrong?

PangoLayout *layout;
#ifdef LEAK     /* leaks memory */
  layout = pango_layout_new(gdk_pango_context_get()); 
  pango_layout_set_text(layout, some_text, -1);
#else   /* doesn't leak memory */
  layout = gtk_widget_create_pango_layout(GTK_WIDGET(window),some_text);
#endif
g_object_unref(layout);

 I've attached a small (less than 120 line) example program. I compiled the 
program with :

gcc -g -o example example.c `pkg-config --libs gtk+-2.0`  \
        `pkg-config --cflags gtk+-2.0`

if you comment out the "#define LEAKS" it won't leak memory. otherwise it 
will. Any help will be appreciated.

----------------------Example program below ------------------------------

#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <string.h>
#include <stdio.h>
#include <time.h>

#define XSIZE 200
#define YSIZE 100
#define LEAKS

GtkWidget *window;
int depth;

gboolean redrawtimer(gpointer data);

void suspectDrawText(GdkDrawable *pixmap, GdkGC *gc, char *m_text)
{
  PangoLayout *layout;
  PangoFontDescription *fontdesc;
  PangoRectangle ink, logical;
        
#ifdef LEAKS    
  layout = pango_layout_new(gdk_pango_context_get());
  pango_layout_set_text(layout, m_text, -1);
#else
  layout = gtk_widget_create_pango_layout(GTK_WIDGET(window),m_text);
#endif
        
  fontdesc = pango_font_description_from_string ("Helvetica Bold 14");
  pango_layout_set_font_description (layout, fontdesc); 
  pango_layout_get_extents(layout,&ink,&logical);
  int howwide = 10, howhigh = ink.height/2/1024 - ink.y/1024;
  gdk_draw_layout(pixmap,gc ,howwide ,howhigh , layout);                
  pango_font_description_free(fontdesc);
  g_object_unref(layout);                       
}

GtkWidget *setWidget(GtkWidget *widgetIn, char *sometext) 
{
  GdkPixmap*  pmap = gdk_pixmap_new(window->window,XSIZE,YSIZE,depth);
  GdkGC*      gc = gdk_gc_new(pmap);

  GdkScreen *pscreen = gdk_screen_get_default();
  GdkColormap* cm = gdk_screen_get_default_colormap(pscreen);

  GdkColor fgcolor;
  if ( gdk_color_parse ("black", &fgcolor)) {
    if (  gdk_colormap_alloc_color(cm, &fgcolor,TRUE,TRUE)) {
      gdk_gc_set_foreground(gc,&fgcolor);
      gdk_draw_rectangle(pmap,gc,TRUE,00,00,XSIZE,YSIZE); // flood it
    }
  }

  GdkColor bgcolor;
  if ( gdk_color_parse ("white", &bgcolor)) {
    if (  gdk_colormap_alloc_color(cm, &bgcolor,TRUE,TRUE)) {
      gdk_gc_set_foreground(gc,&bgcolor);
      suspectDrawText(pmap,gc,sometext);                                
    }
  }
  g_object_unref (gc);
 
  if (widgetIn != NULL) {
    gtk_image_set_from_pixmap ( GTK_IMAGE(widgetIn),pmap,NULL);
  }
  else {
    widgetIn = gtk_image_new_from_pixmap (pmap,NULL);
  }
  g_object_unref (pmap);
  return widgetIn;
}

gboolean redrawtimer(gpointer data)
{
  GtkWidget *theWidget = (GtkWidget *) data;
  time_t now;
  time(&now);
  char *thetime = ctime(&now);
  thetime[19] = 0;
  setWidget(theWidget, thetime +11) ;
  return TRUE;
}

static gboolean delete_event( GtkWidget *widget, GdkEvent  *event, gpointer   
data )
{  
  return FALSE; 
}

static void destroy( GtkWidget *widget, gpointer   data )
{
  gtk_main_quit ();
}


int main( int   argc, char *argv[] )
{
  GtkWidget *image;
  GtkWidget *fixed;

  gtk_init (&argc, &argv);
  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);   /* create a new window */
  fixed =  gtk_fixed_new();
  gtk_container_add (GTK_CONTAINER (window), fixed);
    
  g_signal_connect (G_OBJECT (window), "delete_event",
                    G_CALLBACK (delete_event), NULL);
  g_signal_connect (G_OBJECT (window), "destroy",
                    G_CALLBACK (destroy), NULL);

  gtk_widget_set_size_request (window,XSIZE,YSIZE);
  gtk_widget_show(window);
  depth = gdk_drawable_get_depth(window->window);               
  g_print("Depth = %d\n",depth);
  image =  setWidget(NULL,"Startup");
  gtk_fixed_put(GTK_FIXED(fixed),image,0,0);
  gtk_widget_show_all (window);
  g_timeout_add(100,redrawtimer,image);
  gtk_main ();   // the app sits here in the main loop  
  return 0;
}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]