Commit 87b90ea7 authored by Jürg Billeter's avatar Jürg Billeter

Fix memory leak when freeing arrays of structs

Fixes bug 589144.
parent c070d470
......@@ -378,6 +378,59 @@ internal class Vala.CCodeArrayModule : CCodeMethodCallModule {
}
}
private CCodeForStatement get_struct_array_free_loop (Struct st) {
var cbody = new CCodeBlock ();
var cptrarray = new CCodeIdentifier ("array");
var cea = new CCodeElementAccess (cptrarray, new CCodeIdentifier ("i"));
var cfreecall = new CCodeFunctionCall (get_destroy_func_expression (new StructValueType (st)));
cfreecall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cea));
var cforcond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier ("i"), new CCodeIdentifier ("array_length"));
cbody.add_statement (new CCodeExpressionStatement (cfreecall));
var cfor = new CCodeForStatement (cforcond, cbody);
cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeConstant ("0")));
cfor.add_iterator (new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier ("i"), new CCodeConstant ("1"))));
return cfor;
}
public override string? append_struct_array_free (Struct st) {
string cname = "_vala_%s_array_free".printf (st.get_cname ());;
if (source_declarations.add_declaration (cname)) {
return cname;
}
var fun = new CCodeFunction (cname, "void");
fun.modifiers = CCodeModifiers.STATIC;
fun.add_parameter (new CCodeFormalParameter ("array", "%s*".printf (st.get_cname ())));
fun.add_parameter (new CCodeFormalParameter ("array_length", "gint"));
source_declarations.add_type_member_declaration (fun.copy ());
var cdofree = new CCodeBlock ();
var citdecl = new CCodeDeclaration ("int");
citdecl.add_declarator (new CCodeVariableDeclarator ("i"));
cdofree.add_statement (citdecl);
cdofree.add_statement (get_struct_array_free_loop (st));
var ccondarr = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("array"), new CCodeConstant ("NULL"));
var cif = new CCodeIfStatement (ccondarr, cdofree);
fun.block = new CCodeBlock ();
fun.block.add_statement (cif);
var carrfree = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
carrfree.add_argument (new CCodeIdentifier ("array"));
fun.block.add_statement (new CCodeExpressionStatement (carrfree));
source_type_member_definition.append (fun);
return cname;
}
private CCodeForStatement get_vala_array_free_loop () {
var cbody = new CCodeBlock ();
var cptrarray = new CCodeCastExpression (new CCodeIdentifier ("array"), "gpointer*");
......
......@@ -2106,6 +2106,10 @@ internal class Vala.CCodeBaseModule : CCodeModule {
return destroy_func;
}
public virtual string? append_struct_array_free (Struct st) {
return null;
}
public virtual CCodeExpression get_unref_expression (CCodeExpression cvar, DataType type, Expression expr) {
var ccall = new CCodeFunctionCall (get_destroy_func_expression (type));
......@@ -2159,9 +2163,7 @@ internal class Vala.CCodeBaseModule : CCodeModule {
ccall.add_argument (new CCodeConstant ("TRUE"));
} else if (type is ArrayType) {
var array_type = (ArrayType) type;
if (array_type.element_type.data_type == null || array_type.element_type.data_type.is_reference_type ()) {
requires_array_free = true;
if (requires_destroy (array_type.element_type)) {
CCodeExpression csizeexpr = null;
bool first = true;
for (int dim = 1; dim <= array_type.rank; dim++) {
......@@ -2173,9 +2175,16 @@ internal class Vala.CCodeBaseModule : CCodeModule {
}
}
ccall.call = new CCodeIdentifier ("_vala_array_free");
ccall.add_argument (csizeexpr);
ccall.add_argument (new CCodeCastExpression (get_destroy_func_expression (array_type.element_type), "GDestroyNotify"));
var st = array_type.element_type.data_type as Struct;
if (st != null && !array_type.element_type.nullable) {
ccall.call = new CCodeIdentifier (append_struct_array_free (st));
ccall.add_argument (csizeexpr);
} else {
requires_array_free = true;
ccall.call = new CCodeIdentifier ("_vala_array_free");
ccall.add_argument (csizeexpr);
ccall.add_argument (new CCodeCastExpression (get_destroy_func_expression (array_type.element_type), "GDestroyNotify"));
}
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment