After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 554844 - Vala generated C Code leaks when using a "type instance" derived class
Vala generated C Code leaks when using a "type instance" derived class
Status: RESOLVED FIXED
Product: vala
Classification: Core
Component: Code Generator
0.3.x
Other All
: Normal critical
: ---
Assigned To: Jürg Billeter
Vala maintainers
: 547829 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2008-10-03 12:33 UTC by Andrea Del Signore
Modified: 2008-12-30 21:28 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Unfinished patch (7.69 KB, patch)
2008-10-06 11:01 UTC, Andrea Del Signore
none Details | Review
Program used to test if libvala is memory leak free (886 bytes, text/plain)
2008-10-06 11:04 UTC, Andrea Del Signore
  Details
A better patch (still uncomplete) (8.93 KB, patch)
2008-10-06 21:30 UTC, Andrea Del Signore
reviewed Details | Review

Description Andrea Del Signore 2008-10-03 12:33:33 UTC
Please describe the problem:
Seems that vala generated C Code leaks when using a vala "class" (GLib type instance derived one).

All is ok when I derive from GLib.Object

Steps to reproduce:


Actual results:


Expected results:


Does this happen every time?
Yes

Other information:
Comment 1 Andrea Del Signore 2008-10-03 12:40:03 UTC
This is my vala test program source:

using GLib;
using Gee;

namespace Leaks
{
	public class Item
	{
		public string field = null;
	}

	public class Items
	{
		public Gee.List<Item> items = new Gee.ArrayList<Item> ();
	}

	public static void main (string[] args)
	{
		var test = new Items ();

		test.items.add (new Item ());
		test = null;
		return;
	}
}


This is my valgrind output:

andrea@spavento:~/documenti/src/vala/tests/valas/leaks$ G_SLICE=always-malloc G_DEBUG=gc-friendly GLIBCPP_FORCE_NEW=1 GLIBCXX_FORCE_NEW=1 valgrind --leak-check=full --show-reachable=yes ./gee-test-a
==5272== Memcheck, a memory error detector.
==5272== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et al.
==5272== Using LibVEX rev 1854, a library for dynamic binary translation.
==5272== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP.
==5272== Using valgrind-3.3.1-Debian, a dynamic binary instrumentation framework.
==5272== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et al.
==5272== For more details, rerun with: -v
==5272== 
==5272== 
==5272== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 21 from 1)
==5272== malloc/free: in use at exit: 15,324 bytes in 414 blocks.
==5272== malloc/free: 659 allocs, 245 frees, 190,755 bytes allocated.
==5272== For counts of detected errors, rerun with: -v
==5272== searching for pointers to 414 not-freed blocks.
==5272== checked 89,944 bytes.
==5272== 
==5272== 16 bytes in 1 blocks are indirectly lost in loss record 1 of 8
==5272==    at 0x4023D6E: malloc (vg_replace_malloc.c:207)
==5272==    by 0x40D19D3: g_malloc (gmem.c:131)
==5272==    by 0x40E8302: g_slice_alloc (gslice.c:824)
==5272==    by 0x40E8634: g_slice_alloc0 (gslice.c:833)
==5272==    by 0x407D94A: g_type_create_instance (gtype.c:1654)
==5272==    by 0x8048876: leaks_item_new (gee-test-a.vala:8)
==5272==    by 0x8048A99: leaks_main (gee-test-a.vala:20)
==5272==    by 0x8048B4E: main (gee-test-a.vala:16)
==5272== 
==5272== 
==5272== 16 bytes in 1 blocks are indirectly lost in loss record 2 of 8
==5272==    at 0x4021E22: calloc (vg_replace_malloc.c:397)
==5272==    by 0x40D195B: g_malloc0 (gmem.c:151)
==5272==    by 0x404322E: (within /usr/lib/libgee.so.0.0.0)
==5272==    by 0x407DD02: g_type_create_instance (gtype.c:1674)
==5272==    by 0x40622E4: g_object_constructor (gobject.c:1334)
==5272==    by 0x4062B15: g_object_newv (gobject.c:1211)
==5272==    by 0x4043C97: gee_array_list_new (in /usr/lib/libgee.so.0.0.0)
==5272==    by 0x80489B8: leaks_items_instance_init (gee-test-a.vala:24)
==5272==    by 0x407DD02: g_type_create_instance (gtype.c:1674)
==5272==    by 0x8048965: leaks_items_new (gee-test-a.vala:13)
==5272==    by 0x8048A8A: leaks_main (gee-test-a.vala:20)
==5272==    by 0x8048B4E: main (gee-test-a.vala:16)
==5272== 
==5272== 
==5272== 80 (48 direct, 32 indirect) bytes in 1 blocks are definitely lost in loss record 3 of 8
==5272==    at 0x4023D6E: malloc (vg_replace_malloc.c:207)
==5272==    by 0x40D19D3: g_malloc (gmem.c:131)
==5272==    by 0x40E8302: g_slice_alloc (gslice.c:824)
==5272==    by 0x40E8634: g_slice_alloc0 (gslice.c:833)
==5272==    by 0x407D94A: g_type_create_instance (gtype.c:1654)
==5272==    by 0x40622E4: g_object_constructor (gobject.c:1334)
==5272==    by 0x4062B15: g_object_newv (gobject.c:1211)
==5272==    by 0x4043C97: gee_array_list_new (in /usr/lib/libgee.so.0.0.0)
==5272==    by 0x80489B8: leaks_items_instance_init (gee-test-a.vala:24)
==5272==    by 0x407DD02: g_type_create_instance (gtype.c:1674)
==5272==    by 0x8048965: leaks_items_new (gee-test-a.vala:13)
==5272==    by 0x8048A8A: leaks_main (gee-test-a.vala:20)
==5272== 
==5272== 
==5272== 2,360 bytes in 14 blocks are still reachable in loss record 5 of 8
==5272==    at 0x4023E8C: realloc (vg_replace_malloc.c:429)
==5272==    by 0x40D18B9: g_realloc (gmem.c:170)
==5272==    by 0x405AD93: g_boxed_type_register_static (gbsearcharray.h:216)
==5272==    by 0x405B1A5: g_value_array_get_type (gboxed.c:171)
==5272==    by 0x4068B54: g_param_spec_types_init (gparamspecs.c:1451)
==5272==    by 0x40788DC: g_type_init_with_debug_flags (gtype.c:4067)
==5272==    by 0x4078941: g_type_init (gtype.c:4091)
==5272==    by 0x8048B3D: main (gee-test-a.vala:16)
==5272== 
==5272== 
==5272== 2,456 bytes in 54 blocks are still reachable in loss record 6 of 8
==5272==    at 0x4023D6E: malloc (vg_replace_malloc.c:207)
==5272==    by 0x4023EEF: realloc (vg_replace_malloc.c:429)
==5272==    by 0x40D18B9: g_realloc (gmem.c:170)
==5272==    by 0x40B4F08: g_quark_from_static_string (gdataset.c:683)
==5272==    by 0x4078750: g_type_init_with_debug_flags (gtype.c:4012)
==5272==    by 0x4078941: g_type_init (gtype.c:4091)
==5272==    by 0x8048B3D: main (gee-test-a.vala:16)
==5272== 
==5272== 
==5272== 3,012 bytes in 168 blocks are still reachable in loss record 7 of 8
==5272==    at 0x4023D6E: malloc (vg_replace_malloc.c:207)
==5272==    by 0x40D19D3: g_malloc (gmem.c:131)
==5272==    by 0x40E8302: g_slice_alloc (gslice.c:824)
==5272==    by 0x40BB898: g_hash_table_new_full (ghash.c:347)
==5272==    by 0x40BB927: g_hash_table_new (ghash.c:318)
==5272==    by 0x40B4F3A: g_quark_from_static_string (gdataset.c:687)
==5272==    by 0x4078750: g_type_init_with_debug_flags (gtype.c:4012)
==5272==    by 0x4078941: g_type_init (gtype.c:4091)
==5272==    by 0x8048B3D: main (gee-test-a.vala:16)
==5272== 
==5272== 
==5272== 6,536 bytes in 153 blocks are still reachable in loss record 8 of 8
==5272==    at 0x4021E22: calloc (vg_replace_malloc.c:397)
==5272==    by 0x40D195B: g_malloc0 (gmem.c:151)
==5272==    by 0x40E65EA: g_slice_init_nomessage (gslice.c:329)
==5272==    by 0x40E8374: g_slice_alloc (gslice.c:359)
==5272==    by 0x40BB898: g_hash_table_new_full (ghash.c:347)
==5272==    by 0x40BB927: g_hash_table_new (ghash.c:318)
==5272==    by 0x40B4F3A: g_quark_from_static_string (gdataset.c:687)
==5272==    by 0x4078750: g_type_init_with_debug_flags (gtype.c:4012)
==5272==    by 0x4078941: g_type_init (gtype.c:4091)
==5272==    by 0x8048B3D: main (gee-test-a.vala:16)
==5272== 
==5272== LEAK SUMMARY:
==5272==    definitely lost: 48 bytes in 1 blocks.
==5272==    indirectly lost: 32 bytes in 2 blocks.
==5272==      possibly lost: 0 bytes in 0 blocks.
==5272==    still reachable: 14,364 bytes in 389 blocks.
==5272==         suppressed: 880 bytes in 22 blocks.


Comment 2 Andrea Del Signore 2008-10-03 12:42:26 UTC
Forgot to mention that setting items collection to null solves the leak:

using GLib;
using Gee;

namespace Leaks
{
	public class Item
	{
		public string field = null;
	}

	public class Items
	{
		public Gee.List<Item> items = new Gee.ArrayList<Item> ();
	}

	public static void main (string[] args)
	{
		var test = new Items ();

		test.items.add (new Item ());
                // THIS SOLVES THE LEAK
		test.items = null;
		test = null;
		return;
	}
}

Comment 3 Andrea Del Signore 2008-10-06 11:01:51 UTC
Created attachment 120012 [details] [review]
Unfinished patch

This patch try to fix the leaks. With this applied I get

==867== LEAK SUMMARY:
==867==    definitely lost: 0 bytes in 0 blocks.
==867==      possibly lost: 880 bytes in 22 blocks.
==867==    still reachable: 14,620 bytes in 398 blocks.
==867==         suppressed: 0 bytes in 0 blocks.

And the finalizers seems correct (warning my first time seeing a glib fundamental type), but testing it against libvala itself result in the same huge leak.
Comment 4 Andrea Del Signore 2008-10-06 11:04:05 UTC
Created attachment 120013 [details]
Program used to test if libvala is memory leak free

Compiled with:

 valac --save-temps leaks.vala --pkg vala-1.0

Checked with:

 G_SLICE=always-malloc G_DEBUG=gc-friendly GLIBCPP_FORCE_NEW=1 GLIBCXX_FORCE_NEW=1 valgrind --leak-check=full --show-reachable=yes ./leaks
Comment 5 Andrea Del Signore 2008-10-06 15:26:29 UTC
Finally I've found it, this case still leaks:

    using GLib;

    namespace Leaks
    {

        [Compact]
        private class Node<G> {
            public G key;

            public Node (G# k) {
                key = #k;
            }
        }

        public class Item
        {
            public string field = null;
            public Item (string name) {
                this.field = name;
            }
        }

        public static void main (string[] args)
        {
            var node = new Node<Item> (new Item ("1234"));
            return;
        }
    }
Comment 6 Andrea Del Signore 2008-10-06 21:30:10 UTC
Created attachment 120058 [details] [review]
A better patch (still uncomplete)

This patch solves almost all the leaks.

As a reminder this is what I've found until now:

1) Vala classes (derived just from GTypeInstance) leaks because they don't free their own fields [the patch solves this]

2) Every classes that derives from a fundamental type (1) leaks because they don't free their own fields as in (1) and in that case they need to chain up the destructor [the patch solves this]

3) Every non gobject class isn't freed in the destruction process because vala can't generate a correct unref statement for it [the patch solves this]

4) Every generic compact class leaks the generic values if the ownership is tranferred [the patch *DOESN'T* solve this, but *REMOVES* the [Compact] attribute in the gee hashset & hashmap classes so that they can became normal "vala classes"]
Comment 7 Jürg Billeter 2008-10-17 12:54:59 UTC
2008-10-17  Jürg Billeter  <j@bitron.ch>

	* gobject/valaccodeclassbinding.vala:
	* gobject/valaccodegenerator.vala:
	* vapi/glib-2.0.vapi:

	Fix leaks in non-GObject classes,
	based on patch by Andrea Del Signore, fixes bug 554844

Fixed in r1850.
Comment 8 Jürg Billeter 2008-12-30 21:28:46 UTC
*** Bug 547829 has been marked as a duplicate of this bug. ***