From 60fbceea43263497ad484efdad620b22a1cf78d1 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 25 Mar 2020 12:26:54 +0300 Subject: [PATCH] memory: free_scope_vars() --- vlib/compiler/aparser.v | 2 +- vlib/v/gen/cgen.v | 33 ++++++++++++++++++++------- vlib/v/tests/valgrind/1.vv | 10 ++++++-- vlib/v/tests/valgrind/valgrind_test.v | 3 ++- 4 files changed, 36 insertions(+), 12 deletions(-) diff --git a/vlib/compiler/aparser.v b/vlib/compiler/aparser.v index 56eec65f2b..4dd6428210 100644 --- a/vlib/compiler/aparser.v +++ b/vlib/compiler/aparser.v @@ -451,7 +451,7 @@ fn (p mut Parser) parse(pass Pass) { } p.fgen_nl() p.builtin_mod = p.mod == 'builtin' - p.can_chash = p.mod in ['parser', 'gg2', 'ui', 'uiold', 'darwin', 'clipboard', 'webview'] // TODO tmp remove + p.can_chash = p.mod in ['parser', 'gg2', 'ui', 'uiold', 'darwin', 'clipboard', 'webview', 'gen'] // TODO tmp remove // Import pass - the first and the smallest pass that only analyzes imports // if we are a building module get the full module name from v.mod fq_mod := if p.pref.build_mode == .build_module && p.v.pref.mod.ends_with(p.mod) { p.v.pref.mod } diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 7d2e0a53da..e456aba354 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -662,14 +662,7 @@ fn (g mut Gen) gen_fn_decl(it ast.FnDecl) { g.stmts(it.stmts) // //////////// if g.autofree { - scope := g.file.scope.innermost(it.pos.pos - 1) - for _, var in scope.vars { - sym := g.table.get_type_symbol(var.typ) - if sym.kind == .array && !table.type_is_optional(var.typ) { - g.writeln('array_free($var.name); // autofree') - } - // println(var.name) - } + g.free_scope_vars(it.pos.pos - 1) } // ///////// if is_main { @@ -685,6 +678,30 @@ fn (g mut Gen) gen_fn_decl(it ast.FnDecl) { g.fn_decl = 0 } +fn (g mut Gen) free_scope_vars(pos int) { + scope := g.file.scope.innermost(pos) + for _, var in scope.vars { + sym := g.table.get_type_symbol(var.typ) + if sym.kind == .array && !table.type_is_optional(var.typ) { + g.writeln('array_free($var.name); // autofreed') + } + if sym.kind == .string && !table.type_is_optional(var.typ) { + // Don't free simple string literals. + t := typeof(var.expr) + match var.expr { + ast.StringLiteral { + g.writeln('// str literal') + continue + } + else { + g.writeln('// other' + t) + } + } + g.writeln('string_free($var.name); // autofreed') + } + } +} + fn (g mut Gen) fn_args(args []table.Arg, is_variadic bool) { no_names := args.len > 0 && args[0].name == 'arg_1' for i, arg in args { diff --git a/vlib/v/tests/valgrind/1.vv b/vlib/v/tests/valgrind/1.vv index c4e73b9a14..7b1f596d8f 100644 --- a/vlib/v/tests/valgrind/1.vv +++ b/vlib/v/tests/valgrind/1.vv @@ -7,10 +7,16 @@ fn return_array(array_arg []string) []int { // array argument must not be freed fn foo() { nums := [1, 2, 3] // local array must be freed - nums_copy := nums // array assignments call .clone() println(nums) + + nums_copy := nums // array assignments call .clone() println(nums_copy) - // nums.free() // this should result in a double free and a CI error + + name := 'Peter' // string literals mustn't be freed + str_inter := 'hello, $name' // concatenated strings must be freed + + + //nums.free() // this should result in a double free and a CI error } fn main() { diff --git a/vlib/v/tests/valgrind/valgrind_test.v b/vlib/v/tests/valgrind/valgrind_test.v index 6bbf5ac4dc..8777907bb6 100644 --- a/vlib/v/tests/valgrind/valgrind_test.v +++ b/vlib/v/tests/valgrind/valgrind_test.v @@ -31,8 +31,9 @@ fn test_all() { for test in tests { bench.step() full_test_path := os.real_path(test) + println('x.v: $wrkdir/x.v') os.system('cp ${dir}/${test} $wrkdir/x.v') // cant run .vv file - res := os.exec('$vexe -b v2 $wrkdir/x.v') or { + res := os.exec('$vexe -verbose=3 -b v2 -csource keep -cg $wrkdir/x.v') or { bench.fail() eprintln(bench.step_message_fail('valgrind $test failed')) continue