memory: free_scope_vars()

pull/4113/head
Alexander Medvednikov 2020-03-25 12:26:54 +03:00
parent bb76e5da91
commit 60fbceea43
4 changed files with 36 additions and 12 deletions

View File

@ -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 }

View File

@ -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 {

View File

@ -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() {

View File

@ -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