diff options
author | Rico Tzschichholz <ricotz@ubuntu.com> | 2017-01-20 18:09:38 +0100 |
---|---|---|
committer | Rico Tzschichholz <ricotz@ubuntu.com> | 2017-03-01 09:31:46 +0100 |
commit | d36ce6f5d9329c6b27a7919a9a5874238edcb024 (patch) | |
tree | 70c150005183daeab2db83216440e1694eb054ce | |
parent | f554160c6f54b151e3bf0acc1b214a3a38c05da8 (diff) | |
download | vala-d36ce6f5d9329c6b27a7919a9a5874238edcb024.tar.gz |
codegen: Fix memory leak when using object initializer for properties
Assigning values to properties this way leads to a ref/copy of the source
and therefore requires a unref/destroy afterwards.
https://bugzilla.gnome.org/show_bug.cgi?id=766739
-rw-r--r-- | codegen/valaccodebasemodule.vala | 4 | ||||
-rw-r--r-- | tests/Makefile.am | 1 | ||||
-rw-r--r-- | tests/objects/bug766739.vala | 79 |
3 files changed, 84 insertions, 0 deletions
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala index ecf39c244..3d92f570d 100644 --- a/codegen/valaccodebasemodule.vala +++ b/codegen/valaccodebasemodule.vala @@ -4812,6 +4812,10 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { inst_ma.value_type = expr.type_reference; set_cvalue (inst_ma, instance); store_property ((Property) init.symbol_reference, inst_ma, init.initializer.target_value); + // FIXME Do not ref/copy in the first place + if (requires_destroy (init.initializer.target_value.value_type)) { + ccode.add_expression (destroy_value (init.initializer.target_value)); + } } } diff --git a/tests/Makefile.am b/tests/Makefile.am index 487c990fb..e6fe0f75a 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -173,6 +173,7 @@ TESTS = \ objects/bug751338.vala \ objects/bug767092.test \ objects/bug768823.test \ + objects/bug766739.vala \ errors/errors.vala \ errors/bug567181.vala \ errors/bug579101.vala \ diff --git a/tests/objects/bug766739.vala b/tests/objects/bug766739.vala new file mode 100644 index 000000000..55e974656 --- /dev/null +++ b/tests/objects/bug766739.vala @@ -0,0 +1,79 @@ +struct FooStruct { + public int bar; +} + +class FooClass { + public int bar = 42; +} + + +class Bar { + public int f_simple; + public string f_string; + public string[] f_array; + public FooStruct f_struct; + public FooClass f_class; + + public unowned string fu_string; + public unowned string[] fu_array; + public unowned FooStruct? fu_struct; + public unowned FooClass fu_class; + + public int p_simple { get; set; } + public string p_string { get; set; } + public string[] p_array { get; set; } + public FooStruct p_struct { get; set; } + public FooClass p_class { get; set; } +} + + +void main () { + FooStruct fs = { 42 }; + var fc = new FooClass (); + string s = "foo"; + string[] a = { "foo", "bar" }; + + var bar = new Bar () { + f_simple = 42, + f_string = s, + f_array = a, + f_struct = fs, + f_class = fc, + + fu_string = s, + fu_array = a, + fu_struct = fs, + fu_class = fc, + + p_simple = 42, + p_string = s, + p_array = a, + p_struct = fs, + p_class = fc + }; + + assert (bar.f_simple == 42); + assert (bar.f_string == "foo"); + assert (bar.f_array[1] == "bar"); + assert (bar.f_struct.bar == 42); + assert (bar.f_class == fc); + + assert (bar.fu_string == "foo"); + assert (bar.fu_array[1] == "bar"); + assert (bar.fu_struct == fs); + assert (bar.fu_class == fc); + + assert (bar.p_simple == 42); + assert (bar.p_string == "foo"); + assert (bar.p_array[1] == "bar"); + assert (bar.p_struct.bar == 42); + assert (bar.p_class == fc); + + bar = null; + + assert (fs.bar == 42); + assert (fc.bar == 42); + assert (s == "foo"); + assert (a[1] == "bar"); +} + |