v icon indicating copy to clipboard operation
v copied to clipboard

autofree: memory leak

Open kbkpbot opened this issue 11 months ago • 1 comments

Describe the bug

-autofree should not leak

Reproduction Steps

leak.v

module main

struct MyLeak {
        a u32
}

fn leak_test(leak &MyLeak) {
        println(leak)
}

fn main() {
        leak := MyLeak{}
        leak_test(&leak)
}

then compile

v . -gc none -autofree && valgrind --error-exitcode=1 --leak-check=full --show-reachable=yes ./leak

Expected Behavior

no leak report

Current Behavior

==68272== Memcheck, a memory error detector
==68272== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==68272== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==68272== Command: ./leak
==68272==
&MyLeak{
    a: 0
}
==68272==
==68272== HEAP SUMMARY:
==68272==     in use at exit: 19 bytes in 1 blocks
==68272==   total heap usage: 8 allocs, 7 frees, 1,619 bytes allocated
==68272==
==68272== 19 bytes in 1 blocks are definitely lost in loss record 1 of 1
==68272==    at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==68272==    by 0x6192C1: malloc_noscan (in /home/mars/v/leak/leak)
==68272==    by 0x619D16: memdup_noscan (in /home/mars/v/leak/leak)
==68272==    by 0x6036F8: strings__Builder_str (in /home/mars/v/leak/leak)
==68272==    by 0x632391: str_intp (in /home/mars/v/leak/leak)
==68272==    by 0x602951: indent_main__MyLeak_str (in /home/mars/v/leak/leak)
==68272==    by 0x6025A3: main__MyLeak_str (in /home/mars/v/leak/leak)
==68272==    by 0x63421D: main__leak_test (in /home/mars/v/leak/leak)
==68272==    by 0x6342DE: main__main (in /home/mars/v/leak/leak)
==68272==    by 0x634840: main (in /home/mars/v/leak/leak)
==68272==
==68272== LEAK SUMMARY:
==68272==    definitely lost: 19 bytes in 1 blocks
==68272==    indirectly lost: 0 bytes in 0 blocks
==68272==      possibly lost: 0 bytes in 0 blocks
==68272==    still reachable: 0 bytes in 0 blocks
==68272==         suppressed: 0 bytes in 0 blocks
==68272==
==68272== For lists of detected and suppressed errors, rerun with: -s
==68272== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

Possible Solution

generated c code:

VV_LOCAL_SYMBOL void main__leak_test(main__MyLeak* leak) {
        string _t1 = str_intp(1, _MOV((StrIntpData[]){{_SLIT("&"), 0xfe10 ,{.d_s = isnil(leak) ? _SLIT("nil") : main__MyLeak_str(*leak)}}})); println(_t1); string_free(&_t1);
        ;
}

VV_LOCAL_SYMBOL void main__main(void) {
        main__MyLeak leak = ((main__MyLeak){.a = 0,});
        main__leak_test(&leak);
}

maybe can be modified as follow:

VV_LOCAL_SYMBOL void main__leak_test(main__MyLeak* leak) {
        string _t1 = main__MyLeak_str(*leak);
        string _t2 = str_intp(1, _MOV((StrIntpData[]){{_SLIT("&"), 0xfe10 ,{.d_s = isnil(leak) ? _SLIT("nil") : _t1}}})); string_free(&_t1); println(_t2); string_free(&_t2);
        ;
}

VV_LOCAL_SYMBOL void main__main(void) {
        main__MyLeak leak = ((main__MyLeak){.a = 0,});
        main__leak_test(&leak);
}

Additional Information/Context

No response

V version

V 0.4.4 88bc620.fffb82d

Environment details (OS name and version, etc.)

V full version: V 0.4.4 88bc620.fffb82d OS: linux, Ubuntu 22.04.4 LTS Processor: 8 cpus, 64bit, little endian, Intel(R) Core(TM) i7-9700 CPU @ 3.00GHz

getwd: /home/mars/v/leak vexe: /HD/github/kbkpbot/v/v vexe mtime: 2024-02-19 10:26:50

vroot: OK, value: /HD/github/kbkpbot/v VMODULES: OK, value: /home/mars/.vmodules VTMP: OK, value: /tmp/v_1000

Git version: git version 2.34.1 Git vroot status: weekly.2024.07-48-gd198a898 (28 commit(s) behind V master) .git/config present: true

CC version: cc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0 thirdparty/tcc status: thirdparty-linux-amd64 40e5cbb5-dirty

[!NOTE] You can use the 👍 reaction to increase the issue's priority for developers.

Please note that only the 👍 reaction to the issue itself counts as a vote. Other reactions and those to comments will not be taken into account.

kbkpbot avatar Feb 29 '24 02:02 kbkpbot

This bug is related to how V(c gen) operate on string. For example:

VV_LOCAL_SYMBOL void main__leak_test(main__MyLeak* leak) {
        string _t1 = str_intp(1, _MOV((StrIntpData[]){{_SLIT("&"), 0xfe10 ,{.d_s = isnil(leak) ? _SLIT("nil") : main__MyLeak_str(*leak)}}})); println(_t1); string_free(&_t1);
        ;
}

As the function main__MyLeak_str(*leak) will create a new string on heap, but there is noway free it.

I checked the vlib/gen/c/str.v: fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype ast.Type), it try to generate a string from expr, but this will sometimes alloc a new string on heap.

It need to free somewhere.

kbkpbot avatar Mar 02 '24 12:03 kbkpbot