2009/10/24 Guillaume Cottenceau <gcottenc@gmail.com>
I've made some progress. I have come up with the following C example;
before posting to gnome's bugzilla, I wanted to ask around if it does
make sense? If you have a few minutes to spare ->
http://pastebin.ca/1641693


With the foloowing patch, it does not leak anymore on my debian sid 64.

--- test-unref-orig.c    2009-10-26 14:09:28.550389546 +0100
+++ test-unref.c    2009-10-26 14:10:07.627736671 +0100
@@ -42,8 +42,10 @@
        GError *error = NULL;
        DIR *dir;
        struct dirent *dp;
-       int i;
+       int i,j;
+       int last = count - 1;
        GdkPixbuf* pixbufs[count] = { NULL, };
+       char* file;
 
        gtk_init(&argc, &argv);
 
@@ -58,10 +60,10 @@
        i = 0;
 
        while ((dp = readdir (dir)) != NULL) {
-               char* file = dp->d_name;
-               if (!strstr(file, ".jpg"))
+               file = dp->d_name;
+               if (!(strstr(file, ".jpg")||strstr(file, ".JPG")))
                        continue;
-               printf("Load %s\n", file);
+               // printf("Load %s\n", file);
                pixbufs[i] = gdk_pixbuf_new_from_file(file, &error);
                if (!pixbufs[i]) {
                        fprintf(stderr, "failure loading %s: %s\n",
@@ -70,13 +72,17 @@
                }
                i++;
                if (i == count) {
+                       printf("\nBefore unref\n");
                        display_mem();
                        printf("Unref all but last\n");
-                       for ( i = 0; i < count - 1; i++ )
-                               g_object_unref(pixbufs[i]);
+                       for ( j = 0; j < last; j++ )
+                               g_object_unref(pixbufs[j]);
                        display_mem();
                        // last one becomes first in array
-                       pixbufs[0] = pixbufs[count - 1];
+                       pixbufs[0] = gdk_pixbuf_copy(pixbufs[last]);
+                       g_object_unref(pixbufs[last]);
+                       printf("After putting last in first place\n");
+                       display_mem();
                        i = 1;
                }
        }

Apart from the cosmetic changes, the main difference is I copy the pifbux from last to first, instead of copying the pointer.

I tried a lot of variants, and I suspect "gdk_pixbuf_new_from_file" is keeping some ref around until you clear all ref opened from the function. However my C skill are mostly inexistent, so it may well be something else.
 
On i686, the memory seems to be properly reclaimed, not on x86_64..

I don't have a 32 bits system to test on right now, but I do see the problem on x86_64.

Looks like a bug in GDK to me.

regards

Simon Arnaud