Files
Nim/tests/arc/t23267_result.nim
ringabout 48bfe01a83 fixes #26094; memory leak on exception unwinding — raising proc's res… (#26100)
…ult is never destroyed

fixes #26094



Conceptually, the new lowering for `destination = raisingCall()` is:

```nim
var tmp: T
try:
  tmp = raisingCall()
  let value = tmp
  wasMoved(tmp)
  destination = value
finally:
  destroy(tmp)
```
So whether `raisingCall` Succeeds or not, `tmp` is destroyed

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2026-09-02 12:33:21 +02:00

68 lines
1.3 KiB
Nim

discard """
valgrind: true
cmd: "nim c -d:useMalloc $file"
matrix: "--mm:arc; --mm:orc"
disabled: "freebsd"
disabled: "osx"
disabled: "openbsd"
disabled: "windows"
disabled: "32bit"
"""
import std/options
type Foo = object
id: string
items: seq[string]
proc build(x: int): Foo =
result = Foo(id: "padding-padding", items: @["a", "b", "c"])
if x < 0:
raise newException(ValueError, "boom")
proc parseResult(x: int): Foo =
try:
result = build(x)
except CatchableError:
result = default(Foo)
proc parseVar(x: int; dst: var Foo): bool =
dst = build(x)
result = true
proc parseOption(x: int): Option[Foo] =
result = some(build(x))
const iterations = 10_000
doAssert parseResult(1).items == @["a", "b", "c"]
var successfulDst: Foo
doAssert parseVar(1, successfulDst)
doAssert successfulDst.id == "padding-padding"
doAssert parseOption(1).get.items == @["a", "b", "c"]
var unchangedDst = Foo(id: "old", items: @["old"])
try:
discard parseVar(-1, unchangedDst)
except CatchableError:
discard
doAssert unchangedDst == Foo(id: "old", items: @["old"])
for _ in 0 ..< iterations:
discard parseResult(-1)
for _ in 0 ..< iterations:
var dst: Foo
try:
discard parseVar(-1, dst)
except CatchableError:
discard
for _ in 0 ..< iterations:
try:
discard parseOption(-1)
except CatchableError:
discard