-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Destructor not called for result
when exception is thrown
#22672
Comments
Removing the line which causes the exception makes Valgrind run clean, same for using a variable to store the result and explicitly returning it. |
!nim c --gc:arc -d:useMalloc --expandArc:initMyObj 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 |
@juancarlospaco (collaborator) devel 👍 |
More info on the logs: https://github.com/nim-lang/Nim/actions/runs/6122353948/job/16617925278#step:5:79 |
No need for anything special, result just doesn't receive a call to destroy here. This will eat up memory pretty quick proc leakMemory(): seq[char] =
result = newSeq[char](128)
raise newException(CatchableError, "This is an error")
while true:
try:
discard leakMemory()
except CatchableError:
echo GC_getStatistics() This also leaks, so not exclusive to result ( proc leakMemory(): seq[char] =
var res = newSeq[char](128)
try:
raise newException(CatchableError, "This is an error")
finally:
return res
while true:
try:
discard leakMemory()
except CatchableError:
echo GC_getStatistics() |
Another example: it leaks with ORC import std/json
let startMemory = getOccupiedMem()
for i in 0 .. 10000:
try:
discard parseJson"""{ invalid"""
except:
discard
doAssert(abs(getOccupiedMem() - startMemory) < 4 * 1024 * 1024) |
Just checked to see if this had been fixed in 2.0.4 and it is still present. |
Description
Working further on my MAPM bindings I discovered that throwing exceptions while using
result
caused ARC to not create a destroy call forresult
. My smallest repro currently:Nim Version
v2.0.0 and devel
Current Output
From
--expandArc:initMyObj
:Confirmed with
valgrind --leak-check=full
that it does in fact leak:Expected Output
Based on the output of replacing
result
with a variable and returning it at the end of the function:Possible Solution
No response
Additional Information
No response
The text was updated successfully, but these errors were encountered: