This is a follow up to my last question regarding GTK2 dealing with resource usage.
The application is properly displaying images, however it now appears to be leaking some memory every time GtkImages
are loaded from disk and placed onto a fixed frame for absolute positioning.
I'm using the following basic method called every few seconds to load and display different sets of images.
int DisplaySymbols( GameInfo *m )
{
// variable declarations removed for brevity
// error checking needs to be added
GtkWidget *image;
pos_y = 150;
for( y = 0; y < 3; y++ )
{
pos_x = 187;
for( x = 0; x < 5; x++ )
{
image=gtk_image_new_from_file( fileName );
gtk_fixed_put(GTK_FIXED(frame), image, pos_x, pos_y);
pos_x += symbols[i].pixel_width;
}
pos_y += symbols[i].pixel_height;
}
gtk_widget_show_all(window);
return( 0 );
}
I've read parts of the GTK+
documentation regarding resource usage and I just can't quite figure out how to use the API
calls to prevent memory leaks.
Some thoughts and/or questions I have:
- Should I create some image holding widgets in the fixed frame to more easily manage the images placed in the frame?
- What is my code doing or not doing that is causing memory to be leaked? I'm likely not releasing the
GtkImage
widgets? - It seems a bit inefficient to load the images from disk every time I need to use them. How can I read them into memory and then display them in the frame as needed?
Partial source code is as follows:
//Compile me with: gcc -o leak leak.c $(pkg-config --cflags --libs gtk+-2.0 gmodule-2.0)
// include files removed for brevity
/* GTK */
#include <gdk/gdkx.h>
#include <gtk/gtk.h>
typedef struct
{
unsigned int pixel_width, pixel_height;
gchar fileName[20];
}symbol_t;
static symbol_t symbols[] =
{
/* only showing 2 of eight - brevity */
{ 118, 107, "images/LO.jpg" },
{ 118, 107, "images/L1.jpg" }
};
typedef struct
{
char SpinResult[3][5]; // index of images pointing into symbols struct
}GameInfo;
GameInfo egm;
GtkWidget *frame; /* for absolute positionining of widgets */
GtkWidget *window;
/**** prototypes ****/
// remove for brevity
/********************/
// init random number generator
int Init( void )
{
// create random number - brevity
}
// Determine spin outcome and store into egm.SpinResult array
int DoSpin( GameInfo *egm )
{
// generate matrix of indexes into symbols structure
// so we know what symbols to display in the frame
}
int DisplaySymbols( GameInfo *egm )
{
// variable declarations removed - brevity
GtkWidget *image;
pos_y = 150;
for( y = 0; y < 3; y++ )
{
pos_x = 187;
for( x = 0; x < 5; x++ )
{
image = gtk_image_new_from_file( symbols[i].fileName );
gtk_fixed_put(GTK_FIXED(frame), image, pos_x, pos_y);
pos_x += symbols[i].pixel_width;
}
pos_y += symbols[i].pixel_height;
}
gtk_widget_show_all(window);
return( 0 );
}
void btnSpin_clicked(GtkWidget *button, gpointer data)
{
DoSpin( &egm );
DisplaySymbols( &egm );
return;
}
GtkWidget *SetupWindow(gchar *data, const gchar *filename)
{
// window setup code removed for brevity
return(window);
}
int main (int argc, char *argv[])
{
GtkWidget *btnSpin, *btnExit;
float spinDelay = 2.0;
Init();
gtk_init (&argc, &argv);
window = SetupWindow("Tournament", "images/Midway_Madness_Shell.jpg");
g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (destroy), NULL);
frame = gtk_fixed_new();
gtk_container_add(GTK_CONTAINER(window), frame);
btnSpin = gtk_button_new_with_label("Spin");
gtk_widget_set_size_request(btnSpin, 70, 40);
gtk_fixed_put(GTK_FIXED(frame), btnSpin, 720, 540);
g_signal_connect(G_OBJECT( btnSpin ), "clicked", G_CALLBACK(btnSpin_clicked), NULL );
btnExit = gtk_button_new_with_label("Exit");
gtk_widget_set_size_request(btnExit, 70, 40);
gtk_fixed_put(GTK_FIXED(frame), btnExit, 595, 540);
g_signal_connect(G_OBJECT( btnExit ), "clicked", G_CALLBACK(btnExit_clicked), NULL );
DoSpin( &egm );
DisplaySymbols( &egm );
gtk_widget_show_all(window);
gtk_main ();
return( 0 );
}
I would be very grateful for a detailed explanation of how to resolve this problem as well as some example code as I'm having a hard time understanding how to apply what I've read from the GTK2
documentation which appears to just provide the definition of objects and the function calls. A handsome bounty can be provided if needed for a very thorough response.
If it is useful to have all of the code, I've provided it here.
EDIT: The memory leak was fixed in two ways.
- destroy and re-create the
GtkFixed
container before redrawing the images as suggested by nobar. use a two-dimensional array of pointers to
GtkWidget
to hold the pointers to each image as they are drawn. When it's time to redraw the images the widget pointers in the two-dimensional array are first destroyed like this:int ReleaseImages( void ) { u_int8_t y,x;
/* release images */ for( y = 0; y < 3; y++ ) { for( x = 0; x < 5; x++ ) { gtk_widget_destroy( ptrImages[y][x] ); } } return( 0 );
}
Now the image resources are released and new images can be redrawn.