From: Jürg Billeter Date: Sun, 21 Mar 2010 18:03:52 +0000 (+0100) Subject: Fix memory leak with owned property getters and g_object_get X-Git-Tag: 0.8.0~102 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8974eb665656a24a8efee29f963a84c82ecbac44;p=thirdparty%2Fvala.git Fix memory leak with owned property getters and g_object_get Fixes bug 576152. --- diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala index ded33db26..d25ba871e 100644 --- a/codegen/valaccodebasemodule.vala +++ b/codegen/valaccodebasemodule.vala @@ -478,6 +478,18 @@ internal class Vala.CCodeBaseModule : CCodeModule { } } + public override CCodeIdentifier get_value_taker_function (DataType type_reference) { + var array_type = type_reference as ArrayType; + if (type_reference.data_type != null) { + return new CCodeIdentifier (type_reference.data_type.get_take_value_function ()); + } else if (array_type != null && array_type.element_type.data_type == string_type.data_type) { + // G_TYPE_STRV + return new CCodeIdentifier ("g_value_take_boxed"); + } else { + return new CCodeIdentifier ("g_value_set_pointer"); + } + } + CCodeIdentifier get_value_getter_function (DataType type_reference) { var array_type = type_reference as ArrayType; if (type_reference.data_type != null) { diff --git a/codegen/valaccodemodule.vala b/codegen/valaccodemodule.vala index 939c49fc1..d8e88e316 100644 --- a/codegen/valaccodemodule.vala +++ b/codegen/valaccodemodule.vala @@ -351,6 +351,10 @@ public abstract class Vala.CCodeModule { return next.get_value_setter_function (type_reference); } + public virtual CCodeIdentifier get_value_taker_function (DataType type_reference) { + return next.get_value_taker_function (type_reference); + } + public virtual CCodeExpression get_construct_property_assignment (CCodeConstant canonical_cconstant, DataType property_type, CCodeExpression value) { return next.get_construct_property_assignment (canonical_cconstant, property_type, value); } diff --git a/codegen/valagobjectmodule.vala b/codegen/valagobjectmodule.vala index 6290a68bd..bf5c94db2 100644 --- a/codegen/valagobjectmodule.vala +++ b/codegen/valagobjectmodule.vala @@ -243,7 +243,11 @@ internal class Vala.GObjectModule : GTypeModule { ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_get_%s".printf (prefix, prop.name))); ccall.add_argument (cself); var csetcall = new CCodeFunctionCall (); - csetcall.call = head.get_value_setter_function (prop.property_type); + if (prop.get_accessor.value_type.value_owned) { + csetcall.call = head.get_value_taker_function (prop.property_type); + } else { + csetcall.call = head.get_value_setter_function (prop.property_type); + } csetcall.add_argument (new CCodeIdentifier ("value")); csetcall.add_argument (ccall); cswitch.add_statement (new CCodeExpressionStatement (csetcall)); diff --git a/codegen/valagtypemodule.vala b/codegen/valagtypemodule.vala index 7f6de7ed5..7353e6670 100644 --- a/codegen/valagtypemodule.vala +++ b/codegen/valagtypemodule.vala @@ -136,6 +136,18 @@ internal class Vala.GTypeModule : GErrorModule { decl_space.add_type_member_declaration (function); + function = new CCodeFunction (cl.get_take_value_function (), "void"); + function.add_parameter (new CCodeFormalParameter ("value", "GValue*")); + function.add_parameter (new CCodeFormalParameter ("v_object", "gpointer")); + + if (cl.access == SymbolAccessibility.PRIVATE) { + function.modifiers = CCodeModifiers.STATIC; + // avoid C warning as this function is not always used + function.attributes = "G_GNUC_UNUSED"; + } + + decl_space.add_type_member_declaration (function); + function = new CCodeFunction (cl.get_get_value_function (), "gpointer"); function.add_parameter (new CCodeFormalParameter ("value", "const GValue*")); @@ -537,6 +549,7 @@ internal class Vala.GTypeModule : GErrorModule { add_g_param_spec_type_function (cl); add_g_value_get_function (cl); add_g_value_set_function (cl); + add_g_value_take_function (cl); var ref_count = new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "ref_count"), new CCodeConstant ("1")); instance_init_fragment.append (new CCodeExpressionStatement (ref_count)); @@ -994,6 +1007,76 @@ internal class Vala.GTypeModule : GErrorModule { source_type_member_definition.append (function); } + private void add_g_value_take_function (Class cl) { + var function = new CCodeFunction (cl.get_take_value_function (), "void"); + function.add_parameter (new CCodeFormalParameter ("value", "GValue*")); + function.add_parameter (new CCodeFormalParameter ("v_object", "gpointer")); + + if (cl.access == SymbolAccessibility.PRIVATE) { + function.modifiers = CCodeModifiers.STATIC; + } + + var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer"); + + var init_block = new CCodeBlock (); + function.block = init_block; + + var ctypedecl = new CCodeDeclaration (cl.get_cname()+"*"); + ctypedecl.add_declarator ( new CCodeVariableDeclarator ("old")); + init_block.add_statement (ctypedecl); + + var ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE")); + ccall_typecheck.add_argument (new CCodeIdentifier ( "value" )); + ccall_typecheck.add_argument (new CCodeIdentifier ( cl.get_type_id() )); + + var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail")); + ccall.add_argument (ccall_typecheck); + init_block.add_statement (new CCodeExpressionStatement (ccall)); + + init_block.add_statement(new CCodeExpressionStatement (new CCodeAssignment (new CCodeConstant ("old"), vpointer, CCodeAssignmentOperator.SIMPLE))); + + var true_stmt = new CCodeBlock (); + var false_stmt = new CCodeBlock (); + var if_statement = new CCodeIfStatement (new CCodeIdentifier ("v_object"), true_stmt, false_stmt); + init_block.add_statement (if_statement); + + + ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_INSTANCE_TYPE")); + ccall_typecheck.add_argument (new CCodeIdentifier ( "v_object" )); + ccall_typecheck.add_argument (new CCodeIdentifier ( cl.get_type_id() )); + + ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail")); + ccall.add_argument (ccall_typecheck); + true_stmt.add_statement (new CCodeExpressionStatement (ccall)); + + var ccall_typefrominstance = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE")); + ccall_typefrominstance.add_argument (new CCodeIdentifier ( "v_object" )); + + var ccall_gvaluetype = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE")); + ccall_gvaluetype.add_argument (new CCodeIdentifier ( "value" )); + + var ccall_typecompatible = new CCodeFunctionCall (new CCodeIdentifier ("g_value_type_compatible")); + ccall_typecompatible.add_argument (ccall_typefrominstance); + ccall_typecompatible.add_argument (ccall_gvaluetype); + + ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail")); + ccall.add_argument (ccall_typecompatible); + true_stmt.add_statement (new CCodeExpressionStatement (ccall)); + + true_stmt.add_statement(new CCodeExpressionStatement (new CCodeAssignment (vpointer, new CCodeConstant ("v_object"), CCodeAssignmentOperator.SIMPLE))); + + false_stmt.add_statement(new CCodeExpressionStatement (new CCodeAssignment (vpointer, new CCodeConstant ("NULL"), CCodeAssignmentOperator.SIMPLE))); + + true_stmt = new CCodeBlock (); + if_statement = new CCodeIfStatement (new CCodeIdentifier ("old"), true_stmt); + init_block.add_statement (if_statement); + + ccall = new CCodeFunctionCall (new CCodeIdentifier (cl.get_unref_function ())); + ccall.add_argument (new CCodeIdentifier ("old")); + true_stmt.add_statement (new CCodeExpressionStatement (ccall)); + source_type_member_definition.append (function); + } + private void add_g_value_get_function (Class cl) { var function = new CCodeFunction (cl.get_get_value_function (), "gpointer"); function.add_parameter (new CCodeFormalParameter ("value", "const GValue*")); diff --git a/vala/valaclass.vala b/vala/valaclass.vala index 4fc73a24c..eceedf3ed 100644 --- a/vala/valaclass.vala +++ b/vala/valaclass.vala @@ -123,6 +123,7 @@ public class Vala.Class : ObjectTypeSymbol { private string marshaller_type_name; private string get_value_function; private string set_value_function; + private string take_value_function; private bool _is_compact; private bool _is_immutable; @@ -633,6 +634,9 @@ public class Vala.Class : ObjectTypeSymbol { if (a.has_argument ("set_value_function")) { set_value_function = a.get_string ("set_value_function"); } + if (a.has_argument ("take_value_function")) { + take_value_function = a.get_string ("take_value_function"); + } if (a.has_argument ("const_cname")) { const_cname = a.get_string ("const_cname"); @@ -755,6 +759,22 @@ public class Vala.Class : ObjectTypeSymbol { return set_value_function; } + public override string? get_take_value_function () { + if (take_value_function == null) { + if (is_fundamental ()) { + take_value_function = get_lower_case_cname ("value_take_"); + } else if (base_class != null) { + take_value_function = base_class.get_take_value_function (); + } else if (get_type_id () == "G_TYPE_POINTER") { + take_value_function = "g_value_set_pointer"; + } else { + take_value_function = "g_value_take_boxed"; + } + } + + return take_value_function; + } + public override bool is_reference_counting () { return get_ref_function () != null; } diff --git a/vala/valatypesymbol.vala b/vala/valatypesymbol.vala index 7be7b97ff..996e5dcc8 100644 --- a/vala/valatypesymbol.vala +++ b/vala/valatypesymbol.vala @@ -1,6 +1,7 @@ /* valatypesymbol.vala * - * Copyright (C) 2006-2008 Jürg Billeter, Raffaele Sandrini + * Copyright (C) 2006-2010 Jürg Billeter + * Copyright (C) 2006-2008 Raffaele Sandrini * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -195,7 +196,14 @@ public abstract class Vala.TypeSymbol : Symbol { public virtual string? get_set_value_function () { return null; } - + + /** + * Returns the cname of the GValue taker function. + */ + public virtual string? get_take_value_function () { + return null; + } + /** * Returns the C name of this data type in upper case. Words are * separated by underscores. The upper case C name of the namespace is diff --git a/vapi/glib-2.0.vapi b/vapi/glib-2.0.vapi index e6d2e347f..18872b0ac 100644 --- a/vapi/glib-2.0.vapi +++ b/vapi/glib-2.0.vapi @@ -818,7 +818,7 @@ public enum NormalizeMode { [Compact] [Immutable] -[CCode (cname = "char", const_cname = "const char", copy_function = "g_strdup", free_function = "g_free", cheader_filename = "stdlib.h,string.h,glib.h", type_id = "G_TYPE_STRING", marshaller_type_name = "STRING", param_spec_function = "g_param_spec_string", get_value_function = "g_value_get_string", set_value_function = "g_value_set_string", type_signature = "s")] +[CCode (cname = "char", const_cname = "const char", copy_function = "g_strdup", free_function = "g_free", cheader_filename = "stdlib.h,string.h,glib.h", type_id = "G_TYPE_STRING", marshaller_type_name = "STRING", param_spec_function = "g_param_spec_string", get_value_function = "g_value_get_string", set_value_function = "g_value_set_string", take_value_function = "g_value_take_string", type_signature = "s")] public class string { [CCode (cname = "strstr")] public unowned string? str (string needle); diff --git a/vapi/gobject-2.0.vapi b/vapi/gobject-2.0.vapi index ec9378a6e..2f08988c1 100644 --- a/vapi/gobject-2.0.vapi +++ b/vapi/gobject-2.0.vapi @@ -109,7 +109,7 @@ namespace GLib { public virtual void unload (); } - [CCode (type_id = "G_TYPE_PARAM", ref_function = "g_param_spec_ref", unref_function = "g_param_spec_unref", param_spec_function = "g_param_spec_param", get_value_function = "g_value_get_param", set_value_function = "g_value_set_param")] + [CCode (type_id = "G_TYPE_PARAM", ref_function = "g_param_spec_ref", unref_function = "g_param_spec_unref", param_spec_function = "g_param_spec_param", get_value_function = "g_value_get_param", set_value_function = "g_value_set_param", take_value_function = "g_value_take_param")] public class ParamSpec { public string name; public ParamFlags flags; @@ -288,7 +288,7 @@ namespace GLib { [CCode (instance_pos = 0)] public delegate void WeakNotify (Object object); - [CCode (ref_function = "g_object_ref", unref_function = "g_object_unref", marshaller_type_name = "OBJECT", get_value_function = "g_value_get_object", set_value_function = "g_value_set_object", param_spec_function = "g_param_spec_object", cheader_filename = "glib-object.h")] + [CCode (ref_function = "g_object_ref", unref_function = "g_object_unref", marshaller_type_name = "OBJECT", get_value_function = "g_value_get_object", set_value_function = "g_value_set_object", take_value_function = "g_value_take_object", param_spec_function = "g_param_spec_object", cheader_filename = "glib-object.h")] public class Object { public uint ref_count; @@ -401,7 +401,7 @@ namespace GLib { [CCode (has_target = false)] public delegate void ValueTransform (Value src_value, out Value dest_value); - [CCode (copy_function = "g_value_copy", destroy_function = "g_value_unset", type_id = "G_TYPE_VALUE", marshaller_type_name = "BOXED", get_value_function = "g_value_get_boxed", set_value_function = "g_value_set_boxed", type_signature = "v")] + [CCode (copy_function = "g_value_copy", destroy_function = "g_value_unset", type_id = "G_TYPE_VALUE", marshaller_type_name = "BOXED", get_value_function = "g_value_get_boxed", set_value_function = "g_value_set_boxed", take_value_function = "g_value_take_boxed", type_signature = "v")] public struct Value { [CCode (cname = "G_VALUE_HOLDS")] public bool holds (Type type);