1. pointer in Thing, var param (drawback: you have to make sure that the
pointer stays valid):
type
Thing = object
list: ptr seq[int]
proc initThing(list: var seq[int]): Thing =
result.list = list.addr
Run
2. ref original
var original: ref seq[int]
new(original)
original[] = @[1, 2, 3, 4, 5]
type
Thing = object
list: ref seq[int]
proc initThing(list: ref seq[int]): Thing =
result.list = list
Run
3. cast ptr to ref (drawback: this is a lie, easy to get a reuse after free):
var original = @[1, 2, 3, 4, 5]
type
Thing = object
list: ref seq[int]
proc initThing(list: var seq[int]): Thing =
result.list = cast[ref seq[int]](list.addr)
Run
4. forget about preserving original:
type
Thing = object
list: ref seq[int]
proc initThing(list: seq[int]): Thing =
new(result.list)
result.list[] = list
var thing = initThing(@[1, 2, 3, 4, 5])
let original = thing.list
Run
Example problem with #3:
type
Thing = object
list: ref seq[int]
proc initThing(list: var seq[int]): Thing =
result.list = cast[ref seq[int]](list.addr)
var thing: Thing
new(thing.list)
block:
var original = @[1, 2, 3, 4, 5]
thing = initThing(original)
original[0] = 666
echo thing.list.repr # use after free: ref @[666, 0, 3, 20,
3467820324424670016]
Run