summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRico Tzschichholz <ricotz@ubuntu.com>2017-01-20 18:09:38 +0100
committerRico Tzschichholz <ricotz@ubuntu.com>2017-03-01 09:31:46 +0100
commitd36ce6f5d9329c6b27a7919a9a5874238edcb024 (patch)
tree70c150005183daeab2db83216440e1694eb054ce
parentf554160c6f54b151e3bf0acc1b214a3a38c05da8 (diff)
downloadvala-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.vala4
-rw-r--r--tests/Makefile.am1
-rw-r--r--tests/objects/bug766739.vala79
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");
+}
+