Closed
Description
Description
Working further on my MAPM bindings I discovered that throwing exceptions while using result
caused ARC to not create a destroy call for result
. My smallest repro currently:
import system/ansi_c
type
MyError = object of CatchableError
MyObj = object
internal: pointer
proc `=destroy`(x: MyObj) =
if x.internal.isNil: return
x.internal.c_free
proc `=copy`(x: var MyObj, y: MyObj) =
if x.internal != y.internal:
x.internal.c_free
x.internal = y.internal
proc initMyObj(x: string): MyObj =
result = MyObj(internal: c_malloc(126))
if x.len < 128:
result.internal.copyMem(x[0].addr, x.len)
else:
raise newException(MyError, "This is an error")
import strutils
try:
echo initMyObj("Hello world")
echo initMyObj("Hello world".repeat(128))
except MyError as e:
echo "Got an error!"
echo e.msg
Nim Version
v2.0.0 and devel
Current Output
From --expandArc:initMyObj
:
result = MyObj(internal: c_malloc(126'u))
if len(x) < 128:
copyMem(result.internal, addr(x[0]), chckRange(len(x), 0, 9223372036854775807))
else:
raise
(ref MyError)(msg: "This is an error", parent: nil)
Confirmed with valgrind --leak-check=full
that it does in fact leak:
==1808387== 126 bytes in 1 blocks are definitely lost in loss record 1 of 2
==1808387== at 0x4841848: malloc (vg_replace_malloc.c:431)
==1808387== by 0x10E773: initMyObj__test_u10 (test.nim:18)
==1808387== by 0x10E9DD: NimMainModule (test.nim:28)
==1808387== by 0x109171: NimMainInner (typedthreads.nim:269)
==1808387== by 0x109171: NimMain (typedthreads.nim:280)
==1808387== by 0x109171: main (typedthreads.nim:288)
Expected Output
Based on the output of replacing result
with a variable and returning it at the end of the function:
var res
try:
res = MyObj(internal: c_malloc(126'u))
if len(x) < 128:
copyMem(res.internal, addr(x[0]), chckRange(len(x), 0, 9223372036854775807))
else:
raise
(ref MyError)(msg: "This is an error", parent: nil)
return
result = res
`=wasMoved`(res)
finally:
`=destroy`(res)
Possible Solution
No response
Additional Information
No response
Activity